1 /*
  2  * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2012, 2025 SAP SE. 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/macroAssembler.inline.hpp"
 27 #include "c1/c1_MacroAssembler.hpp"
 28 #include "c1/c1_Runtime1.hpp"
 29 #include "gc/shared/collectedHeap.hpp"
 30 #include "gc/shared/tlab_globals.hpp"
 31 #include "interpreter/interpreter.hpp"
 32 #include "oops/arrayOop.hpp"
 33 #include "oops/markWord.hpp"
 34 #include "runtime/basicLock.hpp"
 35 #include "runtime/os.hpp"
 36 #include "runtime/sharedRuntime.hpp"
 37 #include "runtime/stubRoutines.hpp"
 38 #include "utilities/align.hpp"
 39 #include "utilities/macros.hpp"
 40 #include "utilities/powerOfTwo.hpp"
 41 
 42 
 43 void C1_MacroAssembler::explicit_null_check(Register base) {
 44   Unimplemented();
 45 }
 46 
 47 
 48 void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
 49   const Register return_pc = R20;
 50   mflr(return_pc);
 51 
 52   // Make sure there is enough stack space for this method's activation.
 53   assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
 54   generate_stack_overflow_check(bang_size_in_bytes);
 55 
 56   std(return_pc, _abi0(lr), R1_SP);     // SP->lr = return_pc
 57   push_frame(frame_size_in_bytes, R0); // SP -= frame_size_in_bytes
 58 
 59   BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
 60   bs->nmethod_entry_barrier(this, R20);
 61 }
 62 
 63 
 64 void C1_MacroAssembler::verified_entry(bool breakAtEntry) {
 65   if (breakAtEntry) illtrap();
 66   // build frame
 67 }
 68 
 69 
 70 void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox, Register Rscratch, Label& slow_case) {
 71   assert_different_registers(Rmark, Roop, Rbox, Rscratch);
 72 
 73   Label done, cas_failed, slow_int;
 74 
 75   // The following move must be the first instruction of emitted since debug
 76   // information may be generated for it.
 77   // Load object header.
 78   ld(Rmark, oopDesc::mark_offset_in_bytes(), Roop);
 79 
 80   verify_oop(Roop, FILE_AND_LINE);
 81 
 82   // Save object being locked into the BasicObjectLock...
 83   std(Roop, in_bytes(BasicObjectLock::obj_offset()), Rbox);
 84 
 85   fast_lock(Rbox, Roop, Rmark, Rscratch, slow_int);
 86   b(done);
 87 
 88   bind(slow_int);
 89   b(slow_case); // far
 90 
 91   bind(done);
 92 }
 93 
 94 
 95 void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
 96   assert_different_registers(Rmark, Roop, Rbox);
 97 
 98   Label slow_int, done;
 99 
100   Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
101   assert(mark_addr.disp() == 0, "cas must take a zero displacement");
102 
103   // Load object.
104   ld(Roop, in_bytes(BasicObjectLock::obj_offset()), Rbox);
105   verify_oop(Roop, FILE_AND_LINE);
106 
107   fast_unlock(Roop, Rmark, slow_int);
108   b(done);
109   bind(slow_int);
110   b(slow_case); // far
111 
112   // Done
113   bind(done);
114 }
115 
116 
117 void C1_MacroAssembler::try_allocate(
118   Register obj,                        // result: pointer to object after successful allocation
119   Register var_size_in_bytes,          // object size in bytes if unknown at compile time; invalid otherwise
120   int      con_size_in_bytes,          // object size in bytes if   known at compile time
121   Register t1,                         // temp register
122   Register t2,                         // temp register
123   Label&   slow_case                   // continuation point if fast allocation fails
124 ) {
125   if (UseTLAB) {
126     tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
127   } else {
128     b(slow_case);
129   }
130 }
131 
132 
133 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
134   assert_different_registers(obj, klass, len, t1, t2);
135 
136   if (UseCompactObjectHeaders) {
137     ld(t1, in_bytes(Klass::prototype_header_offset()), klass);
138     std(t1, oopDesc::mark_offset_in_bytes(), obj);
139   } else {
140     load_const_optimized(t1, (intx)markWord::prototype().value());
141     std(t1, oopDesc::mark_offset_in_bytes(), obj);
142     store_klass(obj, klass);
143   }
144 
145   if (len->is_valid()) {
146     stw(len, arrayOopDesc::length_offset_in_bytes(), obj);
147   } else if (!UseCompactObjectHeaders) {
148     // Otherwise length is in the class gap.
149     store_klass_gap(obj);
150   }
151 }
152 
153 
154 void C1_MacroAssembler::initialize_body(Register base, Register index) {
155   assert_different_registers(base, index);
156   srdi(index, index, LogBytesPerWord);
157   clear_memory_doubleword(base, index);
158 }
159 
160 void C1_MacroAssembler::initialize_body(Register obj, Register tmp1, Register tmp2,
161                                         int obj_size_in_bytes, int hdr_size_in_bytes) {
162   const int index = (obj_size_in_bytes - hdr_size_in_bytes) / HeapWordSize;
163 
164   // 2x unrolled loop is shorter with more than 9 HeapWords.
165   if (index <= 9) {
166     clear_memory_unrolled(obj, index, R0, hdr_size_in_bytes);
167   } else {
168     const Register base_ptr = tmp1,
169                    cnt_dwords = tmp2;
170 
171     addi(base_ptr, obj, hdr_size_in_bytes); // Compute address of first element.
172     clear_memory_doubleword(base_ptr, cnt_dwords, R0, index);
173   }
174 }
175 
176 void C1_MacroAssembler::allocate_object(
177   Register obj,                        // result: pointer to object after successful allocation
178   Register t1,                         // temp register
179   Register t2,                         // temp register
180   Register t3,                         // temp register
181   int      hdr_size,                   // object header size in words
182   int      obj_size,                   // object size in words
183   Register klass,                      // object klass
184   Label&   slow_case                   // continuation point if fast allocation fails
185 ) {
186   assert_different_registers(obj, t1, t2, t3, klass);
187 
188   // allocate space & initialize header
189   if (!is_simm16(obj_size * wordSize)) {
190     // Would need to use extra register to load
191     // object size => go the slow case for now.
192     b(slow_case);
193     return;
194   }
195   try_allocate(obj, noreg, obj_size * wordSize, t2, t3, slow_case);
196 
197   initialize_object(obj, klass, noreg, obj_size * HeapWordSize, t1, t2);
198 }
199 
200 void C1_MacroAssembler::initialize_object(
201   Register obj,                        // result: pointer to object after successful allocation
202   Register klass,                      // object klass
203   Register var_size_in_bytes,          // object size in bytes if unknown at compile time; invalid otherwise
204   int      con_size_in_bytes,          // object size in bytes if   known at compile time
205   Register t1,                         // temp register
206   Register t2                          // temp register
207   ) {
208   const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
209 
210   initialize_header(obj, klass, noreg, t1, t2);
211 
212 #ifdef ASSERT
213   {
214     lwz(t1, in_bytes(Klass::layout_helper_offset()), klass);
215     if (var_size_in_bytes != noreg) {
216       cmpw(CR0, t1, var_size_in_bytes);
217     } else {
218       cmpwi(CR0, t1, con_size_in_bytes);
219     }
220     asm_assert_eq("bad size in initialize_object");
221   }
222 #endif
223 
224   // Initialize body.
225   if (var_size_in_bytes != noreg) {
226     // Use a loop.
227     addi(t1, obj, hdr_size_in_bytes);                // Compute address of first element.
228     addi(t2, var_size_in_bytes, -hdr_size_in_bytes); // Compute size of body.
229     initialize_body(t1, t2);
230   } else if (con_size_in_bytes > hdr_size_in_bytes) {
231     // Use a loop.
232     initialize_body(obj, t1, t2, con_size_in_bytes, hdr_size_in_bytes);
233   }
234 
235   if (CURRENT_ENV->dtrace_alloc_probes()) {
236     Unimplemented();
237 //    assert(obj == O0, "must be");
238 //    call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id)),
239 //         relocInfo::runtime_call_type);
240   }
241 
242   verify_oop(obj, FILE_AND_LINE);
243 }
244 
245 
246 void C1_MacroAssembler::allocate_array(
247   Register obj,                        // result: pointer to array after successful allocation
248   Register len,                        // array length
249   Register t1,                         // temp register
250   Register t2,                         // temp register
251   Register t3,                         // temp register
252   int      base_offset_in_bytes,       // elements offset in bytes
253   int      elt_size,                   // element size in bytes
254   Register klass,                      // object klass
255   Label&   slow_case,                  // continuation point if fast allocation fails
256   bool     zero_array                  // zero the allocated array or not
257 ) {
258   assert_different_registers(obj, len, t1, t2, t3, klass);
259 
260   // Determine alignment mask.
261   assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");
262   int log2_elt_size = exact_log2(elt_size);
263 
264   // Check for negative or excessive length.
265   size_t max_length = max_array_allocation_length >> log2_elt_size;
266   if (UseTLAB) {
267     size_t max_tlab = align_up(ThreadLocalAllocBuffer::max_size() >> log2_elt_size, 64*K);
268     if (max_tlab < max_length) { max_length = max_tlab; }
269   }
270   load_const_optimized(t1, max_length);
271   cmpld(CR0, len, t1);
272   bc_far_optimized(Assembler::bcondCRbiIs1, bi0(CR0, Assembler::greater), slow_case);
273 
274   // compute array size
275   // note: If 0 <= len <= max_length, len*elt_size + header + alignment is
276   //       smaller or equal to the largest integer; also, since top is always
277   //       aligned, we can do the alignment here instead of at the end address
278   //       computation.
279   const Register arr_size = t1;
280   Register arr_len_in_bytes = len;
281   if (elt_size != 1) {
282     sldi(t1, len, log2_elt_size);
283     arr_len_in_bytes = t1;
284   }
285   addi(arr_size, arr_len_in_bytes, base_offset_in_bytes + MinObjAlignmentInBytesMask); // Add space for header & alignment.
286   clrrdi(arr_size, arr_size, LogMinObjAlignmentInBytes);                              // Align array size.
287 
288   // Allocate space & initialize header.
289   try_allocate(obj, arr_size, 0, t2, t3, slow_case);
290   initialize_header(obj, klass, len, t2, t3);
291 
292   if (zero_array) {
293     // Initialize body.
294     const Register base  = t2;
295     const Register index = t3;
296     addi(base, obj, base_offset_in_bytes);               // compute address of first element
297     addi(index, arr_size, -(base_offset_in_bytes));      // compute index = number of bytes to clear
298 
299     // Zero first 4 bytes, if start offset is not word aligned.
300     if (!is_aligned(base_offset_in_bytes, BytesPerWord)) {
301       assert(is_aligned(base_offset_in_bytes, BytesPerInt), "must be 4-byte aligned");
302       li(t1, 0);
303       stw(t1, 0, base);
304       addi(base, base, BytesPerInt);
305       // Note: initialize_body will align index down, no need to correct it here.
306     }
307 
308     initialize_body(base, index);
309   }
310 
311   if (CURRENT_ENV->dtrace_alloc_probes()) {
312     Unimplemented();
313     //assert(obj == O0, "must be");
314     //call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(StubId::c1_dtrace_object_alloc_id)),
315     //     relocInfo::runtime_call_type);
316   }
317 
318   verify_oop(obj, FILE_AND_LINE);
319 }
320 
321 
322 #ifndef PRODUCT
323 
324 void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
325   verify_oop_addr((RegisterOrConstant)stack_offset, R1_SP, "broken oop in stack slot");
326 }
327 
328 void C1_MacroAssembler::verify_not_null_oop(Register r) {
329   Label not_null;
330   cmpdi(CR0, r, 0);
331   bne(CR0, not_null);
332   stop("non-null oop required");
333   bind(not_null);
334   verify_oop(r, FILE_AND_LINE);
335 }
336 
337 #endif // PRODUCT
338 
339 void C1_MacroAssembler::null_check(Register r, Label* Lnull) {
340   if (TrapBasedNullChecks) { // SIGTRAP based
341     trap_null_check(r);
342   } else { // explicit
343     //const address exception_entry = Runtime1::entry_for(StubId::c1_throw_null_pointer_exception_id);
344     assert(Lnull != nullptr, "must have Label for explicit check");
345     cmpdi(CR0, r, 0);
346     bc_far_optimized(Assembler::bcondCRbiIs1, bi0(CR0, Assembler::equal), *Lnull);
347   }
348 }