1 /*
  2  * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
  4  * Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
  5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  6  *
  7  * This code is free software; you can redistribute it and/or modify it
  8  * under the terms of the GNU General Public License version 2 only, as
  9  * published by the Free Software Foundation.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  *
 25  */
 26 
 27 #include "asm/macroAssembler.inline.hpp"
 28 #include "interpreter/interp_masm.hpp"
 29 #include "interpreter/interpreter.hpp"
 30 #include "interpreter/interpreterRuntime.hpp"
 31 #include "memory/allocation.inline.hpp"
 32 #include "oops/method.hpp"
 33 #include "oops/oop.inline.hpp"
 34 #include "runtime/handles.inline.hpp"
 35 #include "runtime/icache.hpp"
 36 #include "runtime/interfaceSupport.inline.hpp"
 37 #include "runtime/signature.hpp"
 38 
 39 #define __ _masm->
 40 
 41 // Implementation of SignatureHandlerGenerator
 42 Register InterpreterRuntime::SignatureHandlerGenerator::from() { return rlocals; }
 43 Register InterpreterRuntime::SignatureHandlerGenerator::to()   { return sp; }
 44 Register InterpreterRuntime::SignatureHandlerGenerator::temp() { return rscratch1; }
 45 
 46 Register InterpreterRuntime::SignatureHandlerGenerator::next_gpr() {
 47   if (_num_reg_int_args < Argument::n_int_register_parameters_c-1) {
 48     return as_Register(_num_reg_int_args++ + c_rarg1->encoding());
 49   }
 50   return noreg;
 51 }
 52 
 53 FloatRegister InterpreterRuntime::SignatureHandlerGenerator::next_fpr() {
 54   if (_num_reg_fp_args < Argument::n_float_register_parameters_c) {
 55     return as_FloatRegister(_num_reg_fp_args++);
 56   }
 57   return fnoreg;
 58 }
 59 
 60 // On macos/aarch64 native stack is packed, int/float are using only 4 bytes
 61 // on stack. Natural alignment for types are still in place,
 62 // for example double/long should be 8 bytes aligned.
 63 
 64 int InterpreterRuntime::SignatureHandlerGenerator::next_stack_offset(unsigned elem_size) {
 65   MACOS_ONLY(_stack_offset = align_up(_stack_offset, elem_size));
 66   int ret = _stack_offset;
 67   _stack_offset += NOT_MACOS(wordSize) MACOS_ONLY(elem_size);
 68   return ret;
 69 }
 70 
 71 InterpreterRuntime::SignatureHandlerGenerator::SignatureHandlerGenerator(
 72       const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) {
 73   _masm = new MacroAssembler(buffer);
 74   _num_reg_int_args = (method->is_static() ? 1 : 0);
 75   _num_reg_fp_args = 0;
 76   _stack_offset = 0;
 77 }
 78 
 79 void InterpreterRuntime::SignatureHandlerGenerator::pass_byte() {
 80   const Address src(from(), Interpreter::local_offset_in_bytes(offset()));
 81 
 82   Register reg = next_gpr();
 83   if (reg != noreg) {
 84     __ ldr(reg, src);
 85   } else {
 86     __ ldrb(r0, src);
 87     __ strb(r0, Address(to(), next_stack_offset(sizeof(jbyte))));
 88   }
 89 }
 90 
 91 void InterpreterRuntime::SignatureHandlerGenerator::pass_short() {
 92   const Address src(from(), Interpreter::local_offset_in_bytes(offset()));
 93 
 94   Register reg = next_gpr();
 95   if (reg != noreg) {
 96     __ ldr(reg, src);
 97   } else {
 98     __ ldrh(r0, src);
 99     __ strh(r0, Address(to(), next_stack_offset(sizeof(jshort))));
100   }
101 }
102 
103 void InterpreterRuntime::SignatureHandlerGenerator::pass_int() {
104   const Address src(from(), Interpreter::local_offset_in_bytes(offset()));
105 
106   Register reg = next_gpr();
107   if (reg != noreg) {
108     __ ldr(reg, src);
109   } else {
110     __ ldrw(r0, src);
111     __ strw(r0, Address(to(), next_stack_offset(sizeof(jint))));
112   }
113 }
114 
115 void InterpreterRuntime::SignatureHandlerGenerator::pass_long() {
116   const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1));
117 
118   Register reg = next_gpr();
119   if (reg != noreg) {
120     __ ldr(reg, src);
121   } else {
122     __ ldr(r0, src);
123     __ str(r0, Address(to(), next_stack_offset(sizeof(jlong))));
124   }
125 }
126 
127 void InterpreterRuntime::SignatureHandlerGenerator::pass_float() {
128   const Address src(from(), Interpreter::local_offset_in_bytes(offset()));
129 
130   FloatRegister reg = next_fpr();
131   if (reg != fnoreg) {
132     __ ldrs(reg, src);
133   } else {
134     __ ldrw(r0, src);
135     __ strw(r0, Address(to(), next_stack_offset(sizeof(jfloat))));
136   }
137 }
138 
139 void InterpreterRuntime::SignatureHandlerGenerator::pass_double() {
140   const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1));
141 
142   FloatRegister reg = next_fpr();
143   if (reg != fnoreg) {
144     __ ldrd(reg, src);
145   } else {
146     __ ldr(r0, src);
147     __ str(r0, Address(to(), next_stack_offset(sizeof(jdouble))));
148   }
149 }
150 
151 void InterpreterRuntime::SignatureHandlerGenerator::pass_object() {
152   Register reg = next_gpr();
153   if (reg == c_rarg1) {
154     assert(offset() == 0, "argument register 1 can only be (non-null) receiver");
155     __ add(c_rarg1, from(), Interpreter::local_offset_in_bytes(offset()));
156   } else if (reg != noreg) {
157     __ add(r0, from(), Interpreter::local_offset_in_bytes(offset()));
158     __ mov(reg, 0);
159     __ ldr(temp(), r0);
160     Label L;
161     __ cbz(temp(), L);
162     __ mov(reg, r0);
163     __ bind(L);
164   } else {
165     __ add(r0, from(), Interpreter::local_offset_in_bytes(offset()));
166     __ ldr(temp(), r0);
167     Label L;
168     __ cbnz(temp(), L);
169     __ mov(r0, zr);
170     __ bind(L);
171     static_assert(sizeof(jobject) == wordSize, "");
172     __ str(r0, Address(to(), next_stack_offset(sizeof(jobject))));
173   }
174 }
175 
176 void InterpreterRuntime::SignatureHandlerGenerator::pass_valuetype() {
177    pass_object();
178 }
179 
180 void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprint) {
181   // generate code to handle arguments
182   iterate(fingerprint);
183 
184   // return result handler
185   __ lea(r0, ExternalAddress(Interpreter::result_handler(method()->result_type())));
186   __ ret(lr);
187 
188   __ flush();
189 }
190 
191 
192 // Implementation of SignatureHandlerLibrary
193 
194 void SignatureHandlerLibrary::pd_set_handler(address handler) {}
195 
196 
197 class SlowSignatureHandler
198   : public NativeSignatureIterator {
199  private:
200   address   _from;
201   char*     _to;
202   intptr_t* _int_args;
203   intptr_t* _fp_args;
204   intptr_t* _fp_identifiers;
205   unsigned int _num_reg_int_args;
206   unsigned int _num_reg_fp_args;
207 
208   intptr_t* single_slot_addr() {
209     intptr_t* from_addr = (intptr_t*)(_from+Interpreter::local_offset_in_bytes(0));
210     _from -= Interpreter::stackElementSize;
211     return from_addr;
212   }
213 
214   intptr_t* double_slot_addr() {
215     intptr_t* from_addr = (intptr_t*)(_from+Interpreter::local_offset_in_bytes(1));
216     _from -= 2*Interpreter::stackElementSize;
217     return from_addr;
218   }
219 
220   int pass_gpr(intptr_t value) {
221     if (_num_reg_int_args < Argument::n_int_register_parameters_c-1) {
222       *_int_args++ = value;
223       return _num_reg_int_args++;
224     }
225     return -1;
226   }
227 
228   int pass_fpr(intptr_t value) {
229     if (_num_reg_fp_args < Argument::n_float_register_parameters_c) {
230       *_fp_args++ = value;
231       return _num_reg_fp_args++;
232     }
233     return -1;
234   }
235 
236   template<typename T>
237   void pass_stack(T value) {
238     MACOS_ONLY(_to = align_up(_to, sizeof(value)));
239     *(T *)_to = value;
240     _to += NOT_MACOS(wordSize) MACOS_ONLY(sizeof(value));
241   }
242 
243   virtual void pass_byte() {
244     jbyte value = *(jbyte*)single_slot_addr();
245     if (pass_gpr(value) < 0) {
246       pass_stack<>(value);
247     }
248   }
249 
250   virtual void pass_short() {
251     jshort value = *(jshort*)single_slot_addr();
252     if (pass_gpr(value) < 0) {
253       pass_stack<>(value);
254     }
255   }
256 
257   virtual void pass_int() {
258     jint value = *(jint*)single_slot_addr();
259     if (pass_gpr(value) < 0) {
260       pass_stack<>(value);
261     }
262   }
263 
264   virtual void pass_valuetype() {
265     // values are handled with oops, like objects
266     pass_object();
267   }
268 
269   virtual void pass_long() {
270     intptr_t value = *double_slot_addr();
271     if (pass_gpr(value) < 0) {
272       pass_stack<>(value);
273     }
274   }
275 
276   virtual void pass_object() {
277     intptr_t* addr = single_slot_addr();
278     intptr_t value = *addr == 0 ? (intptr_t)0 : (intptr_t)addr;
279     if (pass_gpr(value) < 0) {
280       pass_stack<>(value);
281     }
282   }
283 
284   virtual void pass_float() {
285     jint value = *(jint*)single_slot_addr();
286     if (pass_fpr(value) < 0) {
287       pass_stack<>(value);
288     }
289   }
290 
291   virtual void pass_double() {
292     intptr_t value = *double_slot_addr();
293     int arg = pass_fpr(value);
294     if (0 <= arg) {
295       *_fp_identifiers |= (1ull << arg); // mark as double
296     } else {
297       pass_stack<>(value);
298     }
299   }
300 
301  public:
302   SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to)
303     : NativeSignatureIterator(method)
304   {
305     _from = from;
306     _to   = (char *)to;
307 
308     _int_args = to - (method->is_static() ? 16 : 17);
309     _fp_args =  to - 8;
310     _fp_identifiers = to - 9;
311     *(int*) _fp_identifiers = 0;
312     _num_reg_int_args = (method->is_static() ? 1 : 0);
313     _num_reg_fp_args = 0;
314   }
315 
316 };
317 
318 
319 JRT_ENTRY(address,
320           InterpreterRuntime::slow_signature_handler(JavaThread* current,
321                                                      Method* method,
322                                                      intptr_t* from,
323                                                      intptr_t* to))
324   methodHandle m(current, (Method*)method);
325   assert(m->is_native(), "sanity check");
326 
327   // handle arguments
328   SlowSignatureHandler ssh(m, (address)from, to);
329   ssh.iterate((uint64_t)CONST64(-1));
330 
331   // return result handler
332   return Interpreter::result_handler(m->result_type());
333 JRT_END