1 /*
2 * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
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
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "asm/assembler.hpp"
27 #include "c1/c1_LIRAssembler.hpp"
28 #include "c1/c1_MacroAssembler.hpp"
29 #include "ci/ciArrayKlass.hpp"
30 #include "oops/objArrayKlass.hpp"
31 #include "runtime/stubRoutines.hpp"
32
33 #define __ _masm->
34
35
36 void LIR_Assembler::generic_arraycopy(Register src, Register src_pos, Register length,
37 Register dst, Register dst_pos, CodeStub *stub) {
38 assert(src == x11 && src_pos == x12, "mismatch in calling convention");
39 // Save the arguments in case the generic arraycopy fails and we
40 // have to fall back to the JNI stub
41 arraycopy_store_args(src, src_pos, length, dst, dst_pos);
42
43 address copyfunc_addr = StubRoutines::generic_arraycopy();
44 assert(copyfunc_addr != nullptr, "generic arraycopy stub required");
45
46 // The arguments are in java calling convention so we shift them
47 // to C convention
48 assert_different_registers(c_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4);
49 __ mv(c_rarg0, j_rarg0);
50 assert_different_registers(c_rarg1, j_rarg2, j_rarg3, j_rarg4);
51 __ mv(c_rarg1, j_rarg1);
52 assert_different_registers(c_rarg2, j_rarg3, j_rarg4);
53 __ mv(c_rarg2, j_rarg2);
54 assert_different_registers(c_rarg3, j_rarg4);
55 __ mv(c_rarg3, j_rarg3);
56 __ mv(c_rarg4, j_rarg4);
57 #ifndef PRODUCT
58 if (PrintC1Statistics) {
59 __ incrementw(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt));
60 }
61 #endif
62 __ far_call(RuntimeAddress(copyfunc_addr));
63 __ beqz(x10, *stub->continuation());
64 // Reload values from the stack so they are where the stub
65 // expects them.
66 arraycopy_load_args(src, src_pos, length, dst, dst_pos);
67
68 // x10 is -1^K where K == partial copied count
69 __ xori(t0, x10, -1);
70 // adjust length down and src/end pos up by partial copied count
71 __ subw(length, length, t0);
72 __ addw(src_pos, src_pos, t0);
73 __ addw(dst_pos, dst_pos, t0);
74 __ j(*stub->entry());
75
76 __ bind(*stub->continuation());
77 }
78
79 void LIR_Assembler::arraycopy_simple_check(Register src, Register src_pos, Register length,
80 Register dst, Register dst_pos, Register tmp,
81 CodeStub *stub, int flags) {
82 // test for null
83 if (flags & LIR_OpArrayCopy::src_null_check) {
84 __ beqz(src, *stub->entry(), /* is_far */ true);
85 }
86 if (flags & LIR_OpArrayCopy::dst_null_check) {
87 __ beqz(dst, *stub->entry(), /* is_far */ true);
88 }
89
90 // If the compiler was not able to prove that exact type of the source or the destination
91 // of the arraycopy is an array type, check at runtime if the source or the destination is
92 // an instance type.
93 if (flags & LIR_OpArrayCopy::type_check) {
94 assert(Klass::_lh_neutral_value == 0, "or replace bgez instructions");
95 if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {
96 __ load_klass(tmp, dst);
97 __ lw(t0, Address(tmp, in_bytes(Klass::layout_helper_offset())));
98 __ bgez(t0, *stub->entry(), /* is_far */ true);
99 }
100
101 if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {
102 __ load_klass(tmp, src);
103 __ lw(t0, Address(tmp, in_bytes(Klass::layout_helper_offset())));
104 __ bgez(t0, *stub->entry(), /* is_far */ true);
105 }
106 }
107
108 // check if negative
109 if (flags & LIR_OpArrayCopy::src_pos_positive_check) {
110 __ bltz(src_pos, *stub->entry(), /* is_far */ true);
111 }
112 if (flags & LIR_OpArrayCopy::dst_pos_positive_check) {
113 __ bltz(dst_pos, *stub->entry(), /* is_far */ true);
114 }
115 if (flags & LIR_OpArrayCopy::length_positive_check) {
116 __ bltz(length, *stub->entry(), /* is_far */ true);
117 }
118
119 if (flags & LIR_OpArrayCopy::src_range_check) {
120 __ addw(tmp, src_pos, length);
121 __ lwu(t0, Address(src, arrayOopDesc::length_offset_in_bytes()));
122 __ bgtu(tmp, t0, *stub->entry(), /* is_far */ true);
123 }
124 if (flags & LIR_OpArrayCopy::dst_range_check) {
125 __ addw(tmp, dst_pos, length);
126 __ lwu(t0, Address(dst, arrayOopDesc::length_offset_in_bytes()));
127 __ bgtu(tmp, t0, *stub->entry(), /* is_far */ true);
128 }
129 }
130
131 void LIR_Assembler::arraycopy_checkcast(Register src, Register src_pos, Register length,
132 Register dst, Register dst_pos, Register tmp,
133 CodeStub *stub, BasicType basic_type,
134 address copyfunc_addr, int flags) {
135 // src is not a sub class of dst so we have to do a
136 // per-element check.
137 int mask = LIR_OpArrayCopy::src_objarray | LIR_OpArrayCopy::dst_objarray;
138 if ((flags & mask) != mask) {
139 // Check that at least both of them object arrays.
140 assert(flags & mask, "one of the two should be known to be an object array");
141
142 if (!(flags & LIR_OpArrayCopy::src_objarray)) {
143 __ load_klass(tmp, src);
144 } else if (!(flags & LIR_OpArrayCopy::dst_objarray)) {
145 __ load_klass(tmp, dst);
146 }
147 int lh_offset = in_bytes(Klass::layout_helper_offset());
148 Address klass_lh_addr(tmp, lh_offset);
149 jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
150 __ lw(t0, klass_lh_addr);
151 __ mv(t1, objArray_lh);
152 __ bne(t0, t1, *stub->entry(), /* is_far */ true);
153 }
154
155 // Spill because stubs can use any register they like and it's
156 // easier to restore just those that we care about.
157 arraycopy_store_args(src, src_pos, length, dst, dst_pos);
158 arraycopy_checkcast_prepare_params(src, src_pos, length, dst, dst_pos, basic_type);
159 __ far_call(RuntimeAddress(copyfunc_addr));
160
161 #ifndef PRODUCT
162 if (PrintC1Statistics) {
163 Label failed;
164 __ bnez(x10, failed);
165 __ incrementw(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_cnt));
166 __ bind(failed);
167 }
168 #endif
169
170 __ beqz(x10, *stub->continuation());
171
172 #ifndef PRODUCT
173 if (PrintC1Statistics) {
174 __ incrementw(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_attempt_cnt));
175 }
176 #endif
177 assert_different_registers(dst, dst_pos, length, src_pos, src, x10, t0);
178
179 // Restore previously spilled arguments
180 arraycopy_load_args(src, src_pos, length, dst, dst_pos);
181
182 // return value is -1^K where K is partial copied count
183 __ xori(t0, x10, -1);
184 // adjust length down and src/end pos up by partial copied count
185 __ subw(length, length, t0);
186 __ addw(src_pos, src_pos, t0);
187 __ addw(dst_pos, dst_pos, t0);
188 }
189
190 void LIR_Assembler::arraycopy_type_check(Register src, Register src_pos, Register length,
191 Register dst, Register dst_pos, Register tmp,
192 CodeStub *stub, BasicType basic_type, int flags) {
193 // We don't know the array types are compatible
194 if (basic_type != T_OBJECT) {
195 // Simple test for basic type arrays
196 if (UseCompactObjectHeaders) {
197 __ load_narrow_klass_compact(tmp, src);
198 __ load_narrow_klass_compact(t0, dst);
199 } else {
200 __ lwu(tmp, Address(src, oopDesc::klass_offset_in_bytes()));
201 __ lwu(t0, Address(dst, oopDesc::klass_offset_in_bytes()));
202 }
203 __ bne(tmp, t0, *stub->entry(), /* is_far */ true);
204 } else {
205 // For object arrays, if src is a sub class of dst then we can
206 // safely do the copy.
207 Label cont, slow;
208
209 #define PUSH(r1, r2) \
210 __ subi(sp, sp, 2 * wordSize); \
211 __ sd(r1, Address(sp, 1 * wordSize)); \
212 __ sd(r2, Address(sp, 0));
213
214 #define POP(r1, r2) \
215 __ ld(r1, Address(sp, 1 * wordSize)); \
216 __ ld(r2, Address(sp, 0)); \
217 __ addi(sp, sp, 2 * wordSize);
218
219 PUSH(src, dst);
220 __ load_klass(src, src);
221 __ load_klass(dst, dst);
222 __ check_klass_subtype_fast_path(src, dst, tmp, &cont, &slow, nullptr);
223
224 PUSH(src, dst);
225 __ far_call(RuntimeAddress(Runtime1::entry_for(StubId::c1_slow_subtype_check_id)));
226 POP(src, dst);
227 __ bnez(dst, cont);
228
229 __ bind(slow);
230 POP(src, dst);
231
232 address copyfunc_addr = StubRoutines::checkcast_arraycopy();
233 if (copyfunc_addr != nullptr) { // use stub if available
234 arraycopy_checkcast(src, src_pos, length, dst, dst_pos, tmp, stub, basic_type, copyfunc_addr, flags);
235 }
236
237 __ j(*stub->entry());
238 __ bind(cont);
239 POP(src, dst);
240 }
241 }
242
243 void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
244 ciArrayKlass *default_type = op->expected_type();
245 Register src = op->src()->as_register();
246 Register dst = op->dst()->as_register();
247 Register src_pos = op->src_pos()->as_register();
248 Register dst_pos = op->dst_pos()->as_register();
249 Register length = op->length()->as_register();
250 Register tmp = op->tmp()->as_register();
251
252 CodeStub* stub = op->stub();
253 int flags = op->flags();
254 BasicType basic_type = default_type != nullptr ? default_type->element_type()->basic_type() : T_ILLEGAL;
255 if (is_reference_type(basic_type)) { basic_type = T_OBJECT; }
256
257 // if we don't know anything, just go through the generic arraycopy
258 if (default_type == nullptr) {
259 generic_arraycopy(src, src_pos, length, dst, dst_pos, stub);
260 return;
261 }
262
263 assert(default_type != nullptr && default_type->is_array_klass() && default_type->is_loaded(),
264 "must be true at this point");
265
266 arraycopy_simple_check(src, src_pos, length, dst, dst_pos, tmp, stub, flags);
267
268 if (flags & LIR_OpArrayCopy::type_check) {
269 arraycopy_type_check(src, src_pos, length, dst, dst_pos, tmp, stub, basic_type, flags);
270 }
271
272 #ifdef ASSERT
273 if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) {
274 // Sanity check the known type with the incoming class. For the
275 // primitive case the types must match exactly with src.klass and
276 // dst.klass each exactly matching the default type. For the
277 // object array case, if no type check is needed then either the
278 // dst type is exactly the expected type and the src type is a
279 // subtype which we can't check or src is the same array as dst
280 // but not necessarily exactly of type default_type.
281 Label known_ok, halt;
282 __ mov_metadata(tmp, default_type->constant_encoding());
283
284 if (basic_type != T_OBJECT) {
285 __ cmp_klass_bne(dst, tmp, t0, t1, halt);
286 __ cmp_klass_beq(src, tmp, t0, t1, known_ok);
287 } else {
288 __ cmp_klass_beq(dst, tmp, t0, t1, known_ok);
289 __ beq(src, dst, known_ok);
290 }
291 __ bind(halt);
292 __ stop("incorrect type information in arraycopy");
293 __ bind(known_ok);
294 }
295 #endif
296
297 #ifndef PRODUCT
298 if (PrintC1Statistics) {
299 __ incrementw(ExternalAddress(Runtime1::arraycopy_count_address(basic_type)));
300 }
301 #endif
302 arraycopy_prepare_params(src, src_pos, length, dst, dst_pos, basic_type);
303
304 bool disjoint = (flags & LIR_OpArrayCopy::overlapping) == 0;
305 bool aligned = (flags & LIR_OpArrayCopy::unaligned) == 0;
306 const char *name = nullptr;
307 address entry = StubRoutines::select_arraycopy_function(basic_type, aligned, disjoint, name, false);
308
309 if (CodeCache::contains(entry)) {
310 __ far_call(RuntimeAddress(entry));
311 } else {
312 const int args_num = 3;
313 __ call_VM_leaf(entry, args_num);
314 }
315
316 if (stub != nullptr) {
317 __ bind(*stub->continuation());
318 }
319 }
320
321
322 void LIR_Assembler::arraycopy_prepare_params(Register src, Register src_pos, Register length,
323 Register dst, Register dst_pos, BasicType basic_type) {
324 int scale = array_element_size(basic_type);
325 __ shadd(c_rarg0, src_pos, src, t0, scale);
326 __ addi(c_rarg0, c_rarg0, arrayOopDesc::base_offset_in_bytes(basic_type));
327 assert_different_registers(c_rarg0, dst, dst_pos, length);
328 __ shadd(c_rarg1, dst_pos, dst, t0, scale);
329 __ addi(c_rarg1, c_rarg1, arrayOopDesc::base_offset_in_bytes(basic_type));
330 assert_different_registers(c_rarg1, dst, length);
331 __ mv(c_rarg2, length);
332 assert_different_registers(c_rarg2, dst);
333 }
334
335 void LIR_Assembler::arraycopy_checkcast_prepare_params(Register src, Register src_pos, Register length,
336 Register dst, Register dst_pos, BasicType basic_type) {
337 arraycopy_prepare_params(src, src_pos, length, dst, dst_pos, basic_type);
338 __ load_klass(c_rarg4, dst);
339 __ ld(c_rarg4, Address(c_rarg4, ObjArrayKlass::element_klass_offset()));
340 __ lwu(c_rarg3, Address(c_rarg4, Klass::super_check_offset_offset()));
341 }
342
343 void LIR_Assembler::arraycopy_store_args(Register src, Register src_pos, Register length,
344 Register dst, Register dst_pos) {
345 __ sd(dst_pos, Address(sp, 0)); // 0: dst_pos sp offset
346 __ sd(dst, Address(sp, 1 * BytesPerWord)); // 1: dst sp offset
347 __ sd(length, Address(sp, 2 * BytesPerWord)); // 2: length sp offset
348 __ sd(src_pos, Address(sp, 3 * BytesPerWord)); // 3: src_pos sp offset
349 __ sd(src, Address(sp, 4 * BytesPerWord)); // 4: src sp offset
350 }
351
352 void LIR_Assembler::arraycopy_load_args(Register src, Register src_pos, Register length,
353 Register dst, Register dst_pos) {
354 __ ld(dst_pos, Address(sp, 0)); // 0: dst_pos sp offset
355 __ ld(dst, Address(sp, 1 * BytesPerWord)); // 1: dst sp offset
356 __ ld(length, Address(sp, 2 * BytesPerWord)); // 2: length sp offset
357 __ ld(src_pos, Address(sp, 3 * BytesPerWord)); // 3: src_pos sp offset
358 __ ld(src, Address(sp, 4 * BytesPerWord)); // 4: src sp offset
359 }
360
361 #undef __