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 __