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 #ifndef SHARE_C1_C1_CODESTUBS_HPP
26 #define SHARE_C1_C1_CODESTUBS_HPP
27
28 #include "c1/c1_FrameMap.hpp"
29 #include "c1/c1_Instruction.hpp"
30 #include "c1/c1_IR.hpp"
31 #include "c1/c1_LIR.hpp"
32 #include "c1/c1_Runtime1.hpp"
33 #include "code/nativeInst.hpp"
34 #include "utilities/growableArray.hpp"
35 #include "utilities/macros.hpp"
36
37 class CodeEmitInfo;
38 class LIR_Assembler;
39 class LIR_OpVisitState;
40
41 // CodeStubs are little 'out-of-line' pieces of code that
42 // usually handle slow cases of operations. All code stubs
43 // are collected and code is emitted at the end of the
44 // nmethod.
45
46 class CodeStub: public CompilationResourceObj {
47 protected:
48 Label _entry; // label at the stub entry point
49 Label _continuation; // label where stub continues, if any
50
51 public:
52 CodeStub() {}
53
54 // code generation
55 void assert_no_unbound_labels() { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); }
56 virtual void emit_code(LIR_Assembler* e) = 0;
57 virtual CodeEmitInfo* info() const { return nullptr; }
58 virtual bool is_exception_throw_stub() const { return false; }
59 virtual bool is_simple_exception_stub() const { return false; }
60 virtual int nr_immediate_oops_patched() const { return 0; }
61 #ifndef PRODUCT
62 virtual void print_name(outputStream* out) const = 0;
63 #endif
64
65 // label access
66 Label* entry() { return &_entry; }
67 Label* continuation() { return &_continuation; }
68 // for LIR
69 virtual void visit(LIR_OpVisitState* visit) = 0;
70 };
71
72 class CodeStubList: public GrowableArray<CodeStub*> {
73 public:
74 CodeStubList(): GrowableArray<CodeStub*>() {}
75
76 void append(CodeStub* stub) {
77 if (!contains(stub)) {
78 GrowableArray<CodeStub*>::append(stub);
79 }
80 }
81 };
82
83 class C1SafepointPollStub: public CodeStub {
84 private:
85 uintptr_t _safepoint_offset;
86
87 public:
88 C1SafepointPollStub() :
89 _safepoint_offset(0) {
90 }
91
92 uintptr_t safepoint_offset() { return _safepoint_offset; }
93 void set_safepoint_offset(uintptr_t safepoint_offset) { _safepoint_offset = safepoint_offset; }
94
95 virtual void emit_code(LIR_Assembler* e);
96 virtual void visit(LIR_OpVisitState* visitor) {
97 // don't pass in the code emit info since it's processed in the fast path
98 visitor->do_slow_case();
99 }
100 #ifndef PRODUCT
101 virtual void print_name(outputStream* out) const { out->print("C1SafepointPollStub"); }
102 #endif // PRODUCT
103 };
104
105 class CounterOverflowStub: public CodeStub {
106 private:
107 CodeEmitInfo* _info;
108 int _bci;
109 LIR_Opr _method;
110
111 public:
112 CounterOverflowStub(CodeEmitInfo* info, int bci, LIR_Opr method) : _info(info), _bci(bci), _method(method) {
113 FrameMap* f = Compilation::current()->frame_map();
114 f->update_reserved_argument_area_size(2 * BytesPerWord);
115 }
116
117 virtual void emit_code(LIR_Assembler* e);
118
119 virtual void visit(LIR_OpVisitState* visitor) {
120 visitor->do_slow_case(_info);
121 visitor->do_input(_method);
122 }
123
124 #ifndef PRODUCT
125 virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); }
126 #endif // PRODUCT
127
128 };
129
130 // Throws ArrayIndexOutOfBoundsException by default but can be
131 // configured to throw IndexOutOfBoundsException in constructor
132 class RangeCheckStub: public CodeStub {
133 private:
134 CodeEmitInfo* _info;
135 LIR_Opr _index;
136 LIR_Opr _array;
137 bool _throw_index_out_of_bounds_exception;
138
139 public:
140 // For ArrayIndexOutOfBoundsException.
141 RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)
142 : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) {
143 assert(info != nullptr, "must have info");
144 _info = new CodeEmitInfo(info);
145 FrameMap* f = Compilation::current()->frame_map();
146 f->update_reserved_argument_area_size(2 * BytesPerWord);
147 }
148 // For IndexOutOfBoundsException.
149 RangeCheckStub(CodeEmitInfo* info, LIR_Opr index)
150 : _index(index), _array(), _throw_index_out_of_bounds_exception(true) {
151 assert(info != nullptr, "must have info");
152 _info = new CodeEmitInfo(info);
153 FrameMap* f = Compilation::current()->frame_map();
154 f->update_reserved_argument_area_size(2 * BytesPerWord);
155 }
156 virtual void emit_code(LIR_Assembler* e);
157 virtual CodeEmitInfo* info() const { return _info; }
158 virtual bool is_exception_throw_stub() const { return true; }
159 virtual void visit(LIR_OpVisitState* visitor) {
160 visitor->do_slow_case(_info);
161 visitor->do_input(_index);
162 if (_array) { visitor->do_input(_array); }
163 }
164 #ifndef PRODUCT
165 virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); }
166 #endif // PRODUCT
167 };
168
169 // stub used when predicate fails and deoptimization is needed
170 class PredicateFailedStub: public CodeStub {
171 private:
172 CodeEmitInfo* _info;
173
174 public:
175 PredicateFailedStub(CodeEmitInfo* info);
176 virtual void emit_code(LIR_Assembler* e);
177 virtual CodeEmitInfo* info() const { return _info; }
178 virtual void visit(LIR_OpVisitState* visitor) {
179 visitor->do_slow_case(_info);
180 }
181 #ifndef PRODUCT
182 virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); }
183 #endif // PRODUCT
184 };
185
186 class DivByZeroStub: public CodeStub {
187 private:
188 CodeEmitInfo* _info;
189 int _offset;
190
191 public:
192 DivByZeroStub(CodeEmitInfo* info)
193 : _info(info), _offset(-1) {
194 }
195 DivByZeroStub(int offset, CodeEmitInfo* info)
196 : _info(info), _offset(offset) {
197 }
198 virtual void emit_code(LIR_Assembler* e);
199 virtual CodeEmitInfo* info() const { return _info; }
200 virtual bool is_exception_throw_stub() const { return true; }
201 virtual void visit(LIR_OpVisitState* visitor) {
202 visitor->do_slow_case(_info);
203 }
204 #ifndef PRODUCT
205 virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); }
206 #endif // PRODUCT
207 };
208
209
210 class ImplicitNullCheckStub: public CodeStub {
211 private:
212 CodeEmitInfo* _info;
213 int _offset;
214
215 public:
216 ImplicitNullCheckStub(int offset, CodeEmitInfo* info)
217 : _info(info), _offset(offset) {
218 }
219 virtual void emit_code(LIR_Assembler* e);
220 virtual CodeEmitInfo* info() const { return _info; }
221 virtual bool is_exception_throw_stub() const { return true; }
222 virtual void visit(LIR_OpVisitState* visitor) {
223 visitor->do_slow_case(_info);
224 }
225 #ifndef PRODUCT
226 virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); }
227 #endif // PRODUCT
228 };
229
230
231 class NewInstanceStub: public CodeStub {
232 private:
233 ciInstanceKlass* _klass;
234 LIR_Opr _klass_reg;
235 LIR_Opr _result;
236 CodeEmitInfo* _info;
237 StubId _stub_id;
238
239 public:
240 NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id);
241 virtual void emit_code(LIR_Assembler* e);
242 virtual CodeEmitInfo* info() const { return _info; }
243 virtual void visit(LIR_OpVisitState* visitor) {
244 visitor->do_slow_case(_info);
245 visitor->do_input(_klass_reg);
246 visitor->do_output(_result);
247 }
248 #ifndef PRODUCT
249 virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); }
250 #endif // PRODUCT
251 };
252
253
254 class NewTypeArrayStub: public CodeStub {
255 private:
256 LIR_Opr _klass_reg;
257 LIR_Opr _length;
258 LIR_Opr _result;
259 CodeEmitInfo* _info;
260
261 public:
262 NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
263 virtual void emit_code(LIR_Assembler* e);
264 virtual CodeEmitInfo* info() const { return _info; }
265 virtual void visit(LIR_OpVisitState* visitor) {
266 visitor->do_slow_case(_info);
267 visitor->do_input(_klass_reg);
268 visitor->do_input(_length);
269 assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
270 }
271 #ifndef PRODUCT
272 virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); }
273 #endif // PRODUCT
274 };
275
276
277 class NewObjectArrayStub: public CodeStub {
278 private:
279 LIR_Opr _klass_reg;
280 LIR_Opr _length;
281 LIR_Opr _result;
282 CodeEmitInfo* _info;
283
284 public:
285 NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
286 virtual void emit_code(LIR_Assembler* e);
287 virtual CodeEmitInfo* info() const { return _info; }
288 virtual void visit(LIR_OpVisitState* visitor) {
289 visitor->do_slow_case(_info);
290 visitor->do_input(_klass_reg);
291 visitor->do_input(_length);
292 assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
293 }
294 #ifndef PRODUCT
295 virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); }
296 #endif // PRODUCT
297 };
298
299
300 class MonitorAccessStub: public CodeStub {
301 protected:
302 LIR_Opr _obj_reg;
303 LIR_Opr _lock_reg;
304
305 public:
306 MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) {
307 _obj_reg = obj_reg;
308 _lock_reg = lock_reg;
309 }
310
311 #ifndef PRODUCT
312 virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); }
313 #endif // PRODUCT
314 };
315
316
317 class MonitorEnterStub: public MonitorAccessStub {
318 private:
319 CodeEmitInfo* _info;
320
321 public:
322 MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info)
323 : MonitorAccessStub(obj_reg, lock_reg) {
324 _info = new CodeEmitInfo(info);
325 FrameMap* f = Compilation::current()->frame_map();
326 f->update_reserved_argument_area_size(2 * BytesPerWord);
327 }
328
329 virtual void emit_code(LIR_Assembler* e);
330 virtual CodeEmitInfo* info() const { return _info; }
331 virtual void visit(LIR_OpVisitState* visitor) {
332 visitor->do_input(_obj_reg);
333 visitor->do_input(_lock_reg);
334 visitor->do_slow_case(_info);
335 }
336 #ifndef PRODUCT
337 virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); }
338 #endif // PRODUCT
339 };
340
341
342 class MonitorExitStub: public MonitorAccessStub {
343 private:
344 int _monitor_ix;
345
346 public:
347 MonitorExitStub(LIR_Opr lock_reg, int monitor_ix)
348 : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),
349 _monitor_ix(monitor_ix) { }
350 virtual void emit_code(LIR_Assembler* e);
351 virtual void visit(LIR_OpVisitState* visitor) {
352 assert(_obj_reg->is_illegal(), "unused");
353 visitor->do_temp(_lock_reg);
354 }
355 #ifndef PRODUCT
356 virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }
357 #endif // PRODUCT
358 };
359
360
361 class PatchingStub: public CodeStub {
362 public:
363 enum PatchID {
364 access_field_id,
365 load_klass_id,
366 load_mirror_id,
367 load_appendix_id
368 };
369 enum constants {
370 patch_info_size = 3
371 };
372 private:
373 PatchID _id;
374 address _pc_start;
375 int _bytes_to_copy;
376 Label _patched_code_entry;
377 Label _patch_site_entry;
378 Label _patch_site_continuation;
379 Register _obj;
380 CodeEmitInfo* _info;
381 int _index; // index of the patchable oop or Klass* in nmethod or metadata table if needed
382 static int _patch_info_offset;
383
384 void align_patch_site(MacroAssembler* masm);
385
386 public:
387 static int patch_info_offset() { return _patch_info_offset; }
388
389 PatchingStub(MacroAssembler* masm, PatchID id, int index = -1):
390 _id(id)
391 , _info(nullptr)
392 , _index(index) {
393 // force alignment of patch sites so we
394 // can guarantee atomic writes to the patch site.
395 align_patch_site(masm);
396 _pc_start = masm->pc();
397 masm->bind(_patch_site_entry);
398 }
399
400 virtual int nr_immediate_oops_patched() const {
401 if (_id == load_mirror_id || _id == load_appendix_id) {
402 return 1;
403 }
404 return 0;
405 }
406
407 void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
408 _info = info;
409 _obj = obj;
410 masm->bind(_patch_site_continuation);
411 _bytes_to_copy = pointer_delta_as_int(masm->pc(), pc_start());
412 if (_id == PatchingStub::access_field_id) {
413 // embed a fixed offset to handle long patches which need to be offset by a word.
414 // the patching code will just add the field offset field to this offset so
415 // that we can reference either the high or low word of a double word field.
416 int field_offset = 0;
417 switch (patch_code) {
418 case lir_patch_low: field_offset = lo_word_offset_in_bytes; break;
419 case lir_patch_high: field_offset = hi_word_offset_in_bytes; break;
420 case lir_patch_normal: field_offset = 0; break;
421 default: ShouldNotReachHere();
422 }
423 NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());
424 n_move->set_offset(field_offset);
425 // Copy will never get executed, so only copy the part which is required for patching.
426 _bytes_to_copy = MAX2(n_move->num_bytes_to_end_of_patch(), (int)NativeGeneralJump::instruction_size);
427 } else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {
428 assert(_obj != noreg, "must have register object for load_klass/load_mirror");
429 #ifdef ASSERT
430 // verify that we're pointing at a NativeMovConstReg
431 nativeMovConstReg_at(pc_start());
432 #endif
433 } else {
434 ShouldNotReachHere();
435 }
436 assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");
437 }
438
439 address pc_start() const { return _pc_start; }
440 PatchID id() const { return _id; }
441
442 virtual void emit_code(LIR_Assembler* e);
443 virtual CodeEmitInfo* info() const { return _info; }
444 virtual void visit(LIR_OpVisitState* visitor) {
445 visitor->do_slow_case(_info);
446 }
447 #ifndef PRODUCT
448 virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }
449 #endif // PRODUCT
450 };
451
452
453 //------------------------------------------------------------------------------
454 // DeoptimizeStub
455 //
456 class DeoptimizeStub : public CodeStub {
457 private:
458 CodeEmitInfo* _info;
459 jint _trap_request;
460
461 public:
462 DeoptimizeStub(CodeEmitInfo* info, Deoptimization::DeoptReason reason, Deoptimization::DeoptAction action) :
463 _info(new CodeEmitInfo(info)), _trap_request(Deoptimization::make_trap_request(reason, action)) {
464 FrameMap* f = Compilation::current()->frame_map();
465 f->update_reserved_argument_area_size(2 * BytesPerWord);
466 }
467
468 virtual void emit_code(LIR_Assembler* e);
469 virtual CodeEmitInfo* info() const { return _info; }
470 virtual bool is_exception_throw_stub() const { return true; }
471 virtual void visit(LIR_OpVisitState* visitor) {
472 visitor->do_slow_case(_info);
473 }
474 #ifndef PRODUCT
475 virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }
476 #endif // PRODUCT
477 };
478
479
480 class SimpleExceptionStub: public CodeStub {
481 private:
482 LIR_Opr _obj;
483 StubId _stub;
484 CodeEmitInfo* _info;
485
486 public:
487 SimpleExceptionStub(StubId stub, LIR_Opr obj, CodeEmitInfo* info):
488 _obj(obj), _stub(stub), _info(info) {
489 FrameMap* f = Compilation::current()->frame_map();
490 f->update_reserved_argument_area_size(2 * BytesPerWord);
491 }
492
493 void set_obj(LIR_Opr obj) {
494 _obj = obj;
495 }
496
497 virtual void emit_code(LIR_Assembler* e);
498 virtual CodeEmitInfo* info() const { return _info; }
499 virtual bool is_exception_throw_stub() const { return true; }
500 virtual bool is_simple_exception_stub() const { return true; }
501 virtual void visit(LIR_OpVisitState* visitor) {
502 if (_obj->is_valid()) visitor->do_input(_obj);
503 visitor->do_slow_case(_info);
504 }
505 #ifndef PRODUCT
506 virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }
507 #endif // PRODUCT
508 };
509
510
511
512 class ArrayStoreExceptionStub: public SimpleExceptionStub {
513 public:
514 ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(StubId::c1_throw_array_store_exception_id, obj, info) {}
515 #ifndef PRODUCT
516 virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }
517 #endif // PRODUCT
518 };
519
520
521 class ArrayCopyStub: public CodeStub {
522 private:
523 LIR_OpArrayCopy* _op;
524
525 public:
526 ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) {
527 FrameMap* f = Compilation::current()->frame_map();
528 f->update_reserved_argument_area_size(arraycopystub_reserved_argument_area_size * BytesPerWord);
529 }
530
531 LIR_Opr src() const { return _op->src(); }
532 LIR_Opr src_pos() const { return _op->src_pos(); }
533 LIR_Opr dst() const { return _op->dst(); }
534 LIR_Opr dst_pos() const { return _op->dst_pos(); }
535 LIR_Opr length() const { return _op->length(); }
536 LIR_Opr tmp() const { return _op->tmp(); }
537
538 virtual void emit_code(LIR_Assembler* e);
539 virtual CodeEmitInfo* info() const { return _op->info(); }
540 virtual void visit(LIR_OpVisitState* visitor) {
541 // don't pass in the code emit info since it's processed in the fast path
542 visitor->do_slow_case();
543 }
544 #ifndef PRODUCT
545 virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }
546 #endif // PRODUCT
547 };
548
549 #endif // SHARE_C1_C1_CODESTUBS_HPP
--- EOF ---