1 /*
  2  * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2014, Red Hat Inc. 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 "precompiled.hpp"
 27 #include "asm/macroAssembler.inline.hpp"
 28 #include "c1/c1_CodeStubs.hpp"
 29 #include "c1/c1_FrameMap.hpp"
 30 #include "c1/c1_LIRAssembler.hpp"
 31 #include "c1/c1_MacroAssembler.hpp"
 32 #include "c1/c1_Runtime1.hpp"
 33 #include "classfile/javaClasses.hpp"
 34 #include "nativeInst_aarch64.hpp"
 35 #include "runtime/sharedRuntime.hpp"
 36 #include "vmreg_aarch64.inline.hpp"
 37 
 38 
 39 #define __ ce->masm()->
 40 
 41 void C1SafepointPollStub::emit_code(LIR_Assembler* ce) {
 42   __ bind(_entry);
 43   InternalAddress safepoint_pc(ce->masm()->pc() - ce->masm()->offset() + safepoint_offset());
 44   __ adr(rscratch1, safepoint_pc);
 45   __ str(rscratch1, Address(rthread, JavaThread::saved_exception_pc_offset()));
 46 
 47   assert(SharedRuntime::polling_page_return_handler_blob() != nullptr,
 48          "polling page return stub not created yet");
 49   address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();
 50 
 51   __ far_jump(RuntimeAddress(stub));
 52 }
 53 
 54 void CounterOverflowStub::emit_code(LIR_Assembler* ce) {
 55   __ bind(_entry);
 56   Metadata *m = _method->as_constant_ptr()->as_metadata();
 57   __ mov_metadata(rscratch1, m);
 58   ce->store_parameter(rscratch1, 1);
 59   ce->store_parameter(_bci, 0);
 60   __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::counter_overflow_id)));
 61   ce->add_call_info_here(_info);
 62   ce->verify_oop_map(_info);
 63   __ b(_continuation);
 64 }
 65 
 66 void RangeCheckStub::emit_code(LIR_Assembler* ce) {
 67   __ bind(_entry);
 68   if (_info->deoptimize_on_exception()) {
 69     address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id);
 70     __ far_call(RuntimeAddress(a));
 71     ce->add_call_info_here(_info);
 72     ce->verify_oop_map(_info);
 73     debug_only(__ should_not_reach_here());
 74     return;
 75   }
 76 
 77   if (_index->is_cpu_register()) {
 78     __ mov(rscratch1, _index->as_register());
 79   } else {
 80     __ mov(rscratch1, _index->as_jint());
 81   }
 82   C1StubId stub_id;
 83   if (_throw_index_out_of_bounds_exception) {
 84     stub_id = C1StubId::throw_index_exception_id;
 85   } else {
 86     assert(_array != LIR_Opr::nullOpr(), "sanity");
 87     __ mov(rscratch2, _array->as_pointer_register());
 88     stub_id = C1StubId::throw_range_check_failed_id;
 89   }
 90   __ lea(lr, RuntimeAddress(Runtime1::entry_for(stub_id)));
 91   __ blr(lr);
 92   ce->add_call_info_here(_info);
 93   ce->verify_oop_map(_info);
 94   debug_only(__ should_not_reach_here());
 95 }
 96 
 97 PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
 98   _info = new CodeEmitInfo(info);
 99 }
100 
101 void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
102   __ bind(_entry);
103   address a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id);
104   __ far_call(RuntimeAddress(a));
105   ce->add_call_info_here(_info);
106   ce->verify_oop_map(_info);
107   debug_only(__ should_not_reach_here());
108 }
109 
110 void DivByZeroStub::emit_code(LIR_Assembler* ce) {
111   if (_offset != -1) {
112     ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
113   }
114   __ bind(_entry);
115   __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::throw_div0_exception_id)));
116   ce->add_call_info_here(_info);
117   ce->verify_oop_map(_info);
118 #ifdef ASSERT
119   __ should_not_reach_here();
120 #endif
121 }
122 
123 
124 
125 // Implementation of NewInstanceStub
126 
127 NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) {
128   _result = result;
129   _klass = klass;
130   _klass_reg = klass_reg;
131   _info = new CodeEmitInfo(info);
132   assert(stub_id == C1StubId::new_instance_id                 ||
133          stub_id == C1StubId::fast_new_instance_id            ||
134          stub_id == C1StubId::fast_new_instance_init_check_id,
135          "need new_instance id");
136   _stub_id   = stub_id;
137 }
138 
139 
140 
141 void NewInstanceStub::emit_code(LIR_Assembler* ce) {
142   assert(__ rsp_offset() == 0, "frame size should be fixed");
143   __ bind(_entry);
144   __ mov(r3, _klass_reg->as_register());
145   __ far_call(RuntimeAddress(Runtime1::entry_for(_stub_id)));
146   ce->add_call_info_here(_info);
147   ce->verify_oop_map(_info);
148   assert(_result->as_register() == r0, "result must in r0,");
149   __ b(_continuation);
150 }
151 
152 
153 // Implementation of NewTypeArrayStub
154 
155 // Implementation of NewTypeArrayStub
156 
157 NewTypeArrayStub::NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) {
158   _klass_reg = klass_reg;
159   _length = length;
160   _result = result;
161   _info = new CodeEmitInfo(info);
162 }
163 
164 
165 void NewTypeArrayStub::emit_code(LIR_Assembler* ce) {
166   assert(__ rsp_offset() == 0, "frame size should be fixed");
167   __ bind(_entry);
168   assert(_length->as_register() == r19, "length must in r19,");
169   assert(_klass_reg->as_register() == r3, "klass_reg must in r3");
170   __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_type_array_id)));
171   ce->add_call_info_here(_info);
172   ce->verify_oop_map(_info);
173   assert(_result->as_register() == r0, "result must in r0");
174   __ b(_continuation);
175 }
176 
177 
178 // Implementation of NewObjectArrayStub
179 
180 NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) {
181   _klass_reg = klass_reg;
182   _result = result;
183   _length = length;
184   _info = new CodeEmitInfo(info);
185 }
186 
187 
188 void NewObjectArrayStub::emit_code(LIR_Assembler* ce) {
189   assert(__ rsp_offset() == 0, "frame size should be fixed");
190   __ bind(_entry);
191   assert(_length->as_register() == r19, "length must in r19,");
192   assert(_klass_reg->as_register() == r3, "klass_reg must in r3");
193   __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::new_object_array_id)));
194   ce->add_call_info_here(_info);
195   ce->verify_oop_map(_info);
196   assert(_result->as_register() == r0, "result must in r0");
197   __ b(_continuation);
198 }
199 
200 void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
201   assert(__ rsp_offset() == 0, "frame size should be fixed");
202   __ bind(_entry);
203   ce->store_parameter(_obj_reg->as_register(),  1);
204   ce->store_parameter(_lock_reg->as_register(), 0);
205   C1StubId enter_id;
206   if (ce->compilation()->has_fpu_code()) {
207     enter_id = C1StubId::monitorenter_id;
208   } else {
209     enter_id = C1StubId::monitorenter_nofpu_id;
210   }
211   __ far_call(RuntimeAddress(Runtime1::entry_for(enter_id)));
212   ce->add_call_info_here(_info);
213   ce->verify_oop_map(_info);
214   __ b(_continuation);
215 }
216 
217 
218 void MonitorExitStub::emit_code(LIR_Assembler* ce) {
219   __ bind(_entry);
220   if (_compute_lock) {
221     // lock_reg was destroyed by fast unlocking attempt => recompute it
222     ce->monitor_address(_monitor_ix, _lock_reg);
223   }
224   ce->store_parameter(_lock_reg->as_register(), 0);
225   // note: non-blocking leaf routine => no call info needed
226   C1StubId exit_id;
227   if (ce->compilation()->has_fpu_code()) {
228     exit_id = C1StubId::monitorexit_id;
229   } else {
230     exit_id = C1StubId::monitorexit_nofpu_id;
231   }
232   __ adr(lr, _continuation);
233   __ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id)));
234 }
235 
236 
237 // Implementation of patching:
238 // - Copy the code at given offset to an inlined buffer (first the bytes, then the number of bytes)
239 // - Replace original code with a call to the stub
240 // At Runtime:
241 // - call to stub, jump to runtime
242 // - in runtime: preserve all registers (rspecially objects, i.e., source and destination object)
243 // - in runtime: after initializing class, restore original code, reexecute instruction
244 
245 int PatchingStub::_patch_info_offset = -NativeGeneralJump::instruction_size;
246 
247 void PatchingStub::align_patch_site(MacroAssembler* masm) {
248 }
249 
250 void PatchingStub::emit_code(LIR_Assembler* ce) {
251   assert(false, "AArch64 should not use C1 runtime patching");
252 }
253 
254 
255 void DeoptimizeStub::emit_code(LIR_Assembler* ce) {
256   __ bind(_entry);
257   ce->store_parameter(_trap_request, 0);
258   __ far_call(RuntimeAddress(Runtime1::entry_for(C1StubId::deoptimize_id)));
259   ce->add_call_info_here(_info);
260   DEBUG_ONLY(__ should_not_reach_here());
261 }
262 
263 
264 void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
265   address a;
266   if (_info->deoptimize_on_exception()) {
267     // Deoptimize, do not throw the exception, because it is probably wrong to do it here.
268     a = Runtime1::entry_for(C1StubId::predicate_failed_trap_id);
269   } else {
270     a = Runtime1::entry_for(C1StubId::throw_null_pointer_exception_id);
271   }
272 
273   ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
274   __ bind(_entry);
275   __ far_call(RuntimeAddress(a));
276   ce->add_call_info_here(_info);
277   ce->verify_oop_map(_info);
278   debug_only(__ should_not_reach_here());
279 }
280 
281 
282 void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
283   assert(__ rsp_offset() == 0, "frame size should be fixed");
284 
285   __ bind(_entry);
286   // pass the object in a scratch register because all other registers
287   // must be preserved
288   if (_obj->is_cpu_register()) {
289     __ mov(rscratch1, _obj->as_register());
290   }
291   __ far_call(RuntimeAddress(Runtime1::entry_for(_stub)), rscratch2);
292   ce->add_call_info_here(_info);
293   debug_only(__ should_not_reach_here());
294 }
295 
296 
297 void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
298   //---------------slow case: call to native-----------------
299   __ bind(_entry);
300   // Figure out where the args should go
301   // This should really convert the IntrinsicID to the Method* and signature
302   // but I don't know how to do that.
303   //
304   VMRegPair args[5];
305   BasicType signature[5] = { T_OBJECT, T_INT, T_OBJECT, T_INT, T_INT};
306   SharedRuntime::java_calling_convention(signature, args, 5);
307 
308   // push parameters
309   // (src, src_pos, dest, destPos, length)
310   Register r[5];
311   r[0] = src()->as_register();
312   r[1] = src_pos()->as_register();
313   r[2] = dst()->as_register();
314   r[3] = dst_pos()->as_register();
315   r[4] = length()->as_register();
316 
317   // next registers will get stored on the stack
318   for (int i = 0; i < 5 ; i++ ) {
319     VMReg r_1 = args[i].first();
320     if (r_1->is_stack()) {
321       int st_off = r_1->reg2stack() * wordSize;
322       __ str (r[i], Address(sp, st_off));
323     } else {
324       assert(r[i] == args[i].first()->as_Register(), "Wrong register for arg ");
325     }
326   }
327 
328   ce->align_call(lir_static_call);
329 
330   ce->emit_static_call_stub();
331   if (ce->compilation()->bailed_out()) {
332     return; // CodeCache is full
333   }
334   Address resolve(SharedRuntime::get_resolve_static_call_stub(),
335                   relocInfo::static_call_type);
336   address call = __ trampoline_call(resolve);
337   if (call == nullptr) {
338     ce->bailout("trampoline stub overflow");
339     return;
340   }
341   ce->add_call_info_here(info());
342 
343 #ifndef PRODUCT
344   if (PrintC1Statistics) {
345     __ lea(rscratch2, ExternalAddress((address)&Runtime1::_arraycopy_slowcase_cnt));
346     __ incrementw(Address(rscratch2));
347   }
348 #endif
349 
350   __ b(_continuation);
351 }
352 
353 #undef __