1 /*
  2  * Copyright (c) 1999, 2025, 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 "c1/c1_MacroAssembler.hpp"
 26 #include "c1/c1_Runtime1.hpp"
 27 #include "code/compiledIC.hpp"
 28 #include "compiler/compilerDefinitions.inline.hpp"
 29 #include "gc/shared/barrierSet.hpp"
 30 #include "gc/shared/barrierSetAssembler.hpp"
 31 #include "gc/shared/collectedHeap.hpp"
 32 #include "gc/shared/tlab_globals.hpp"
 33 #include "interpreter/interpreter.hpp"
 34 #include "oops/arrayOop.hpp"
 35 #include "oops/markWord.hpp"
 36 #include "runtime/basicLock.hpp"
 37 #include "runtime/globals.hpp"
 38 #include "runtime/os.hpp"
 39 #include "runtime/sharedRuntime.hpp"
 40 #include "runtime/stubRoutines.hpp"
 41 #include "utilities/checkedCast.hpp"
 42 #include "utilities/globalDefinitions.hpp"
 43 
 44 int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
 45   const int aligned_mask = BytesPerWord -1;
 46   const int hdr_offset = oopDesc::mark_offset_in_bytes();
 47   assert(hdr == rax, "hdr must be rax, for the cmpxchg instruction");
 48   assert_different_registers(hdr, obj, disp_hdr, tmp);
 49   int null_check_offset = -1;
 50 
 51   verify_oop(obj);
 52 
 53   // save object being locked into the BasicObjectLock
 54   movptr(Address(disp_hdr, BasicObjectLock::obj_offset()), obj);
 55 
 56   null_check_offset = offset();
 57 
 58   if (LockingMode == LM_LIGHTWEIGHT) {
 59     lightweight_lock(disp_hdr, obj, hdr, tmp, slow_case);
 60   } else  if (LockingMode == LM_LEGACY) {
 61     Label done;
 62 
 63     if (DiagnoseSyncOnValueBasedClasses != 0) {
 64       load_klass(hdr, obj, rscratch1);
 65       testb(Address(hdr, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
 66       jcc(Assembler::notZero, slow_case);
 67     }
 68 
 69     // Load object header
 70     movptr(hdr, Address(obj, hdr_offset));
 71     // and mark it as unlocked
 72     orptr(hdr, markWord::unlocked_value);
 73     // save unlocked object header into the displaced header location on the stack
 74     movptr(Address(disp_hdr, 0), hdr);
 75     // test if object header is still the same (i.e. unlocked), and if so, store the
 76     // displaced header address in the object header - if it is not the same, get the
 77     // object header instead
 78     MacroAssembler::lock(); // must be immediately before cmpxchg!
 79     cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
 80     // if the object header was the same, we're done
 81     jcc(Assembler::equal, done);
 82     // if the object header was not the same, it is now in the hdr register
 83     // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
 84     //
 85     // 1) (hdr & aligned_mask) == 0
 86     // 2) rsp <= hdr
 87     // 3) hdr <= rsp + page_size
 88     //
 89     // these 3 tests can be done by evaluating the following expression:
 90     //
 91     // (hdr - rsp) & (aligned_mask - page_size)
 92     //
 93     // assuming both the stack pointer and page_size have their least
 94     // significant 2 bits cleared and page_size is a power of 2
 95     subptr(hdr, rsp);
 96     andptr(hdr, aligned_mask - (int)os::vm_page_size());
 97     // for recursive locking, the result is zero => save it in the displaced header
 98     // location (null in the displaced hdr location indicates recursive locking)
 99     movptr(Address(disp_hdr, 0), hdr);
100     // otherwise we don't care about the result and handle locking via runtime call
101     jcc(Assembler::notZero, slow_case);
102     // done
103     bind(done);
104     inc_held_monitor_count();
105   }
106 
107   return null_check_offset;
108 }
109 
110 void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
111   const int aligned_mask = BytesPerWord -1;
112   const int hdr_offset = oopDesc::mark_offset_in_bytes();
113   assert(disp_hdr == rax, "disp_hdr must be rax, for the cmpxchg instruction");
114   assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");
115   Label done;
116 
117   if (LockingMode != LM_LIGHTWEIGHT) {
118     // load displaced header
119     movptr(hdr, Address(disp_hdr, 0));
120     // if the loaded hdr is null we had recursive locking
121     testptr(hdr, hdr);
122     // if we had recursive locking, we are done
123     jcc(Assembler::zero, done);
124   }
125 
126   // load object
127   movptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
128   verify_oop(obj);
129 
130   if (LockingMode == LM_LIGHTWEIGHT) {
131     lightweight_unlock(obj, disp_hdr, hdr, slow_case);
132   } else if (LockingMode == LM_LEGACY) {
133     // test if object header is pointing to the displaced header, and if so, restore
134     // the displaced header in the object - if the object header is not pointing to
135     // the displaced header, get the object header instead
136     MacroAssembler::lock(); // must be immediately before cmpxchg!
137     cmpxchgptr(hdr, Address(obj, hdr_offset));
138     // if the object header was not pointing to the displaced header,
139     // we do unlocking via runtime call
140     jcc(Assembler::notEqual, slow_case);
141     // done
142     bind(done);
143     dec_held_monitor_count();
144   }
145 }
146 
147 
148 // Defines obj, preserves var_size_in_bytes
149 void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {
150   if (UseTLAB) {
151     tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
152   } else {
153     jmp(slow_case);
154   }
155 }
156 
157 
158 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
159   assert_different_registers(obj, klass, len, t1, t2);
160   if (UseCompactObjectHeaders) {
161     movptr(t1, Address(klass, Klass::prototype_header_offset()));
162     movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1);
163   } else if (UseCompressedClassPointers) { // Take care not to kill klass
164     movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
165     movptr(t1, klass);
166     encode_klass_not_null(t1, rscratch1);
167     movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
168   } else {
169     movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
170     movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
171   }
172 
173   if (len->is_valid()) {
174     movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
175     int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
176     if (!is_aligned(base_offset, BytesPerWord)) {
177       assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
178       // Clear gap/first 4 bytes following the length field.
179       xorl(t1, t1);
180       movl(Address(obj, base_offset), t1);
181     }
182   } else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
183     xorptr(t1, t1);
184     store_klass_gap(obj, t1);
185   }
186 }
187 
188 
189 // preserves obj, destroys len_in_bytes
190 void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {
191   assert(hdr_size_in_bytes >= 0, "header size must be positive or 0");
192   Label done;
193 
194   // len_in_bytes is positive and ptr sized
195   subptr(len_in_bytes, hdr_size_in_bytes);
196   zero_memory(obj, len_in_bytes, hdr_size_in_bytes, t1);
197   bind(done);
198 }
199 
200 
201 void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {
202   assert(obj == rax, "obj must be in rax, for cmpxchg");
203   assert_different_registers(obj, t1, t2); // XXX really?
204   assert(header_size >= 0 && object_size >= header_size, "illegal sizes");
205 
206   try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);
207 
208   initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2, UseTLAB);
209 }
210 
211 void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, bool is_tlab_allocated) {
212   assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
213          "con_size_in_bytes is not multiple of alignment");
214   const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
215   if (UseCompactObjectHeaders) {
216     assert(hdr_size_in_bytes == 8, "check object headers size");
217   }
218   initialize_header(obj, klass, noreg, t1, t2);
219 
220   if (!(UseTLAB && ZeroTLAB && is_tlab_allocated)) {
221     // clear rest of allocated space
222     const Register t1_zero = t1;
223     const Register index = t2;
224     const int threshold = 6 * BytesPerWord;   // approximate break even point for code size (see comments below)
225     if (var_size_in_bytes != noreg) {
226       mov(index, var_size_in_bytes);
227       initialize_body(obj, index, hdr_size_in_bytes, t1_zero);
228     } else if (con_size_in_bytes <= threshold) {
229       // use explicit null stores
230       // code size = 2 + 3*n bytes (n = number of fields to clear)
231       xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code)
232       for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord)
233         movptr(Address(obj, i), t1_zero);
234     } else if (con_size_in_bytes > hdr_size_in_bytes) {
235       // use loop to null out the fields
236       // code size = 16 bytes for even n (n = number of fields to clear)
237       // initialize last object field first if odd number of fields
238       xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code)
239       movptr(index, (con_size_in_bytes - hdr_size_in_bytes) >> 3);
240       // initialize last object field if constant size is odd
241       if (((con_size_in_bytes - hdr_size_in_bytes) & 4) != 0)
242         movptr(Address(obj, con_size_in_bytes - (1*BytesPerWord)), t1_zero);
243       // initialize remaining object fields: rdx is a multiple of 2
244       { Label loop;
245         bind(loop);
246         movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (1*BytesPerWord)),
247                t1_zero);
248         decrement(index);
249         jcc(Assembler::notZero, loop);
250       }
251     }
252   }
253 
254   if (CURRENT_ENV->dtrace_alloc_probes()) {
255     assert(obj == rax, "must be");
256     call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id)));
257   }
258 
259   verify_oop(obj);
260 }
261 
262 void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int base_offset_in_bytes, Address::ScaleFactor f, Register klass, Label& slow_case, bool zero_array) {
263   assert(obj == rax, "obj must be in rax, for cmpxchg");
264   assert_different_registers(obj, len, t1, t2, klass);
265 
266   // determine alignment mask
267   assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");
268 
269   // check for negative or excessive length
270   cmpptr(len, checked_cast<int32_t>(max_array_allocation_length));
271   jcc(Assembler::above, slow_case);
272 
273   const Register arr_size = t2; // okay to be the same
274   // align object end
275   movptr(arr_size, base_offset_in_bytes + MinObjAlignmentInBytesMask);
276   lea(arr_size, Address(arr_size, len, f));
277   andptr(arr_size, ~MinObjAlignmentInBytesMask);
278 
279   try_allocate(obj, arr_size, 0, t1, t2, slow_case);
280 
281   initialize_header(obj, klass, len, t1, t2);
282 
283   // clear rest of allocated space
284   if (zero_array) {
285     const Register len_zero = len;
286     // Align-up to word boundary, because we clear the 4 bytes potentially
287     // following the length field in initialize_header().
288     int base_offset = align_up(base_offset_in_bytes, BytesPerWord);
289     initialize_body(obj, arr_size, base_offset, len_zero);
290   }
291 
292   if (CURRENT_ENV->dtrace_alloc_probes()) {
293     assert(obj == rax, "must be");
294     call(RuntimeAddress(Runtime1::entry_for(C1StubId::dtrace_object_alloc_id)));
295   }
296 
297   verify_oop(obj);
298 }
299 
300 void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
301   assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
302   // Make sure there is enough stack space for this method's activation.
303   // Note that we do this before doing an enter(). This matches the
304   // ordering of C2's stack overflow check / rsp decrement and allows
305   // the SharedRuntime stack overflow handling to be consistent
306   // between the two compilers.
307   generate_stack_overflow_check(bang_size_in_bytes);
308 
309   push(rbp);
310   if (PreserveFramePointer) {
311     mov(rbp, rsp);
312   }
313   decrement(rsp, frame_size_in_bytes); // does not emit code for frame_size == 0
314 
315   BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
316   // C1 code is not hot enough to micro optimize the nmethod entry barrier with an out-of-line stub
317   bs->nmethod_entry_barrier(this, nullptr /* slow_path */, nullptr /* continuation */);
318 }
319 
320 
321 void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) {
322   increment(rsp, frame_size_in_bytes);  // Does not emit code for frame_size == 0
323   pop(rbp);
324 }
325 
326 
327 void C1_MacroAssembler::verified_entry(bool breakAtEntry) {
328   if (breakAtEntry) {
329     // Verified Entry first instruction should be 5 bytes long for correct
330     // patching by patch_verified_entry().
331     //
332     // Breakpoint has one byte first instruction.
333     // Also first instruction will be one byte "push(rbp)" if stack banging
334     // code is not generated (see build_frame() above).
335     // For all these cases generate long instruction first.
336     fat_nop();
337   }
338   if (breakAtEntry) int3();
339   // build frame
340 }
341 
342 void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) {
343   // rbp, + 0: link
344   //     + 1: return address
345   //     + 2: argument with offset 0
346   //     + 3: argument with offset 1
347   //     + 4: ...
348 
349   movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord));
350 }
351 
352 #ifndef PRODUCT
353 
354 void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
355   if (!VerifyOops) return;
356   verify_oop_addr(Address(rsp, stack_offset));
357 }
358 
359 void C1_MacroAssembler::verify_not_null_oop(Register r) {
360   if (!VerifyOops) return;
361   Label not_null;
362   testptr(r, r);
363   jcc(Assembler::notZero, not_null);
364   stop("non-null oop required");
365   bind(not_null);
366   verify_oop(r);
367 }
368 
369 void C1_MacroAssembler::invalidate_registers(bool inv_rax, bool inv_rbx, bool inv_rcx, bool inv_rdx, bool inv_rsi, bool inv_rdi) {
370 #ifdef ASSERT
371   if (inv_rax) movptr(rax, 0xDEAD);
372   if (inv_rbx) movptr(rbx, 0xDEAD);
373   if (inv_rcx) movptr(rcx, 0xDEAD);
374   if (inv_rdx) movptr(rdx, 0xDEAD);
375   if (inv_rsi) movptr(rsi, 0xDEAD);
376   if (inv_rdi) movptr(rdi, 0xDEAD);
377 #endif
378 }
379 
380 #endif // ifndef PRODUCT