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 class ConversionStub: public CodeStub {
131 private:
132 Bytecodes::Code _bytecode;
133 LIR_Opr _input;
134 LIR_Opr _result;
135
136 static float float_zero;
137 static double double_zero;
138 public:
139 ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result)
140 : _bytecode(bytecode), _input(input), _result(result) {
141 NOT_IA32( ShouldNotReachHere(); ) // used only on x86-32
142 }
143
144 Bytecodes::Code bytecode() { return _bytecode; }
145 LIR_Opr input() { return _input; }
146 LIR_Opr result() { return _result; }
147
148 virtual void emit_code(LIR_Assembler* e);
149 virtual void visit(LIR_OpVisitState* visitor) {
150 visitor->do_slow_case();
151 visitor->do_input(_input);
152 visitor->do_output(_result);
153 }
154 #ifndef PRODUCT
155 virtual void print_name(outputStream* out) const { out->print("ConversionStub"); }
156 #endif // PRODUCT
157 };
158
159
160 // Throws ArrayIndexOutOfBoundsException by default but can be
161 // configured to throw IndexOutOfBoundsException in constructor
162 class RangeCheckStub: public CodeStub {
163 private:
164 CodeEmitInfo* _info;
165 LIR_Opr _index;
166 LIR_Opr _array;
167 bool _throw_index_out_of_bounds_exception;
168
169 public:
170 // For ArrayIndexOutOfBoundsException.
171 RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array)
172 : _index(index), _array(array), _throw_index_out_of_bounds_exception(false) {
173 assert(info != nullptr, "must have info");
174 _info = new CodeEmitInfo(info);
175 FrameMap* f = Compilation::current()->frame_map();
176 f->update_reserved_argument_area_size(2 * BytesPerWord);
177 }
178 // For IndexOutOfBoundsException.
179 RangeCheckStub(CodeEmitInfo* info, LIR_Opr index)
180 : _index(index), _array(), _throw_index_out_of_bounds_exception(true) {
181 assert(info != nullptr, "must have info");
182 _info = new CodeEmitInfo(info);
183 FrameMap* f = Compilation::current()->frame_map();
184 f->update_reserved_argument_area_size(2 * BytesPerWord);
185 }
186 virtual void emit_code(LIR_Assembler* e);
187 virtual CodeEmitInfo* info() const { return _info; }
188 virtual bool is_exception_throw_stub() const { return true; }
189 virtual void visit(LIR_OpVisitState* visitor) {
190 visitor->do_slow_case(_info);
191 visitor->do_input(_index);
192 if (_array) { visitor->do_input(_array); }
193 }
194 #ifndef PRODUCT
195 virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); }
196 #endif // PRODUCT
197 };
198
199 // stub used when predicate fails and deoptimization is needed
200 class PredicateFailedStub: public CodeStub {
201 private:
202 CodeEmitInfo* _info;
203
204 public:
205 PredicateFailedStub(CodeEmitInfo* info);
206 virtual void emit_code(LIR_Assembler* e);
207 virtual CodeEmitInfo* info() const { return _info; }
208 virtual void visit(LIR_OpVisitState* visitor) {
209 visitor->do_slow_case(_info);
210 }
211 #ifndef PRODUCT
212 virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); }
213 #endif // PRODUCT
214 };
215
216 class DivByZeroStub: public CodeStub {
217 private:
218 CodeEmitInfo* _info;
219 int _offset;
220
221 public:
222 DivByZeroStub(CodeEmitInfo* info)
223 : _info(info), _offset(-1) {
224 }
225 DivByZeroStub(int offset, CodeEmitInfo* info)
226 : _info(info), _offset(offset) {
227 }
228 virtual void emit_code(LIR_Assembler* e);
229 virtual CodeEmitInfo* info() const { return _info; }
230 virtual bool is_exception_throw_stub() const { return true; }
231 virtual void visit(LIR_OpVisitState* visitor) {
232 visitor->do_slow_case(_info);
233 }
234 #ifndef PRODUCT
235 virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); }
236 #endif // PRODUCT
237 };
238
239
240 class ImplicitNullCheckStub: public CodeStub {
241 private:
242 CodeEmitInfo* _info;
243 int _offset;
244
245 public:
246 ImplicitNullCheckStub(int offset, CodeEmitInfo* info)
247 : _info(info), _offset(offset) {
248 }
249 virtual void emit_code(LIR_Assembler* e);
250 virtual CodeEmitInfo* info() const { return _info; }
251 virtual bool is_exception_throw_stub() const { return true; }
252 virtual void visit(LIR_OpVisitState* visitor) {
253 visitor->do_slow_case(_info);
254 }
255 #ifndef PRODUCT
256 virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); }
257 #endif // PRODUCT
258 };
259
260
261 class LoadFlattenedArrayStub: public CodeStub {
262 private:
263 LIR_Opr _array;
264 LIR_Opr _index;
265 LIR_Opr _result;
266 LIR_Opr _scratch_reg;
267 CodeEmitInfo* _info;
268
269 public:
270 LoadFlattenedArrayStub(LIR_Opr array, LIR_Opr index, LIR_Opr result, CodeEmitInfo* info);
271 virtual void emit_code(LIR_Assembler* e);
272 virtual CodeEmitInfo* info() const { return _info; }
273 virtual void visit(LIR_OpVisitState* visitor) {
274 visitor->do_slow_case(_info);
275 visitor->do_input(_array);
276 visitor->do_input(_index);
277 visitor->do_output(_result);
278 if (_scratch_reg != LIR_OprFact::illegalOpr) {
279 visitor->do_temp(_scratch_reg);
280 }
281 }
282
283 #ifndef PRODUCT
284 virtual void print_name(outputStream* out) const { out->print("LoadFlattenedArrayStub"); }
285 #endif // PRODUCT
286 };
287
288
289 class StoreFlattenedArrayStub: public CodeStub {
290 private:
291 LIR_Opr _array;
292 LIR_Opr _index;
293 LIR_Opr _value;
294 LIR_Opr _scratch_reg;
295 CodeEmitInfo* _info;
296
297 public:
298 StoreFlattenedArrayStub(LIR_Opr array, LIR_Opr index, LIR_Opr value, CodeEmitInfo* info);
299 virtual void emit_code(LIR_Assembler* e);
300 virtual CodeEmitInfo* info() const { return _info; }
301 virtual void visit(LIR_OpVisitState* visitor) {
302 visitor->do_slow_case(_info);
303 visitor->do_input(_array);
304 visitor->do_input(_index);
305 visitor->do_input(_value);
306 if (_scratch_reg != LIR_OprFact::illegalOpr) {
307 visitor->do_temp(_scratch_reg);
308 }
309 }
310 #ifndef PRODUCT
311 virtual void print_name(outputStream* out) const { out->print("StoreFlattenedArrayStub"); }
312 #endif // PRODUCT
313 };
314
315 class SubstitutabilityCheckStub: public CodeStub {
316 private:
317 LIR_Opr _left;
318 LIR_Opr _right;
319 LIR_Opr _scratch_reg;
320 CodeEmitInfo* _info;
321 public:
322 SubstitutabilityCheckStub(LIR_Opr left, LIR_Opr right, CodeEmitInfo* info);
323 virtual void emit_code(LIR_Assembler* e);
324 virtual CodeEmitInfo* info() const { return _info; }
325 virtual void visit(LIR_OpVisitState* visitor) {
326 visitor->do_slow_case(_info);
327 visitor->do_input(_left);
328 visitor->do_input(_right);
329 if (_scratch_reg != LIR_OprFact::illegalOpr) {
330 visitor->do_temp(_scratch_reg);
331 }
332 }
333 #ifndef PRODUCT
334 virtual void print_name(outputStream* out) const { out->print("SubstitutabilityCheckStub"); }
335 #endif // PRODUCT
336 };
337
338 class NewInstanceStub: public CodeStub {
339 private:
340 ciInstanceKlass* _klass;
341 LIR_Opr _klass_reg;
342 LIR_Opr _result;
343 CodeEmitInfo* _info;
344 StubId _stub_id;
345
346 public:
347 NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, StubId stub_id);
348 virtual void emit_code(LIR_Assembler* e);
349 virtual CodeEmitInfo* info() const { return _info; }
350 virtual void visit(LIR_OpVisitState* visitor) {
351 visitor->do_slow_case(_info);
352 visitor->do_input(_klass_reg);
353 visitor->do_output(_result);
354 }
355 #ifndef PRODUCT
356 virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); }
357 #endif // PRODUCT
358 };
359
360
361 class NewTypeArrayStub: public CodeStub {
362 private:
363 LIR_Opr _klass_reg;
364 LIR_Opr _length;
365 LIR_Opr _result;
366 CodeEmitInfo* _info;
367
368 public:
369 NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);
370 virtual void emit_code(LIR_Assembler* e);
371 virtual CodeEmitInfo* info() const { return _info; }
372 virtual void visit(LIR_OpVisitState* visitor) {
373 visitor->do_slow_case(_info);
374 visitor->do_input(_klass_reg);
375 visitor->do_input(_length);
376 assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
377 }
378 #ifndef PRODUCT
379 virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); }
380 #endif // PRODUCT
381 };
382
383
384 class NewObjectArrayStub: public CodeStub {
385 private:
386 LIR_Opr _klass_reg;
387 LIR_Opr _length;
388 LIR_Opr _result;
389 CodeEmitInfo* _info;
390 bool _is_null_free;
391 public:
392 NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info, bool is_null_free);
393 virtual void emit_code(LIR_Assembler* e);
394 virtual CodeEmitInfo* info() const { return _info; }
395 virtual void visit(LIR_OpVisitState* visitor) {
396 visitor->do_slow_case(_info);
397 visitor->do_input(_klass_reg);
398 visitor->do_input(_length);
399 assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);
400 }
401 #ifndef PRODUCT
402 virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); }
403 #endif // PRODUCT
404 };
405
406
407 class MonitorAccessStub: public CodeStub {
408 protected:
409 LIR_Opr _obj_reg;
410 LIR_Opr _lock_reg;
411
412 public:
413 MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) {
414 _obj_reg = obj_reg;
415 _lock_reg = lock_reg;
416 }
417
418 #ifndef PRODUCT
419 virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); }
420 #endif // PRODUCT
421 };
422
423
424 class MonitorEnterStub: public MonitorAccessStub {
425 private:
426 CodeEmitInfo* _info;
427 CodeStub* _throw_ie_stub;
428 LIR_Opr _scratch_reg;
429
430 public:
431 MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info,
432 CodeStub* throw_ie_stub = nullptr, LIR_Opr scratch_reg = LIR_OprFact::illegalOpr)
433 : MonitorAccessStub(obj_reg, lock_reg) {
434 _info = new CodeEmitInfo(info);
435 _scratch_reg = scratch_reg;
436 _throw_ie_stub = throw_ie_stub;
437 if (_throw_ie_stub != nullptr) {
438 assert(_scratch_reg != LIR_OprFact::illegalOpr, "must be");
439 }
440 FrameMap* f = Compilation::current()->frame_map();
441 f->update_reserved_argument_area_size(2 * BytesPerWord);
442 }
443
444 virtual void emit_code(LIR_Assembler* e);
445 virtual CodeEmitInfo* info() const { return _info; }
446 virtual void visit(LIR_OpVisitState* visitor) {
447 visitor->do_input(_obj_reg);
448 visitor->do_input(_lock_reg);
449 if (_scratch_reg != LIR_OprFact::illegalOpr) {
450 visitor->do_temp(_scratch_reg);
451 }
452 visitor->do_slow_case(_info);
453 }
454 #ifndef PRODUCT
455 virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); }
456 #endif // PRODUCT
457 };
458
459
460 class MonitorExitStub: public MonitorAccessStub {
461 private:
462 int _monitor_ix;
463
464 public:
465 MonitorExitStub(LIR_Opr lock_reg, int monitor_ix)
466 : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),
467 _monitor_ix(monitor_ix) { }
468 virtual void emit_code(LIR_Assembler* e);
469 virtual void visit(LIR_OpVisitState* visitor) {
470 assert(_obj_reg->is_illegal(), "unused");
471 visitor->do_temp(_lock_reg);
472 }
473 #ifndef PRODUCT
474 virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }
475 #endif // PRODUCT
476 };
477
478
479 class PatchingStub: public CodeStub {
480 public:
481 enum PatchID {
482 access_field_id,
483 load_klass_id,
484 load_mirror_id,
485 load_appendix_id
486 };
487 enum constants {
488 patch_info_size = 3
489 };
490 private:
491 PatchID _id;
492 address _pc_start;
493 int _bytes_to_copy;
494 Label _patched_code_entry;
495 Label _patch_site_entry;
496 Label _patch_site_continuation;
497 Register _obj;
498 CodeEmitInfo* _info;
499 int _index; // index of the patchable oop or Klass* in nmethod or metadata table if needed
500 static int _patch_info_offset;
501
502 void align_patch_site(MacroAssembler* masm);
503
504 public:
505 static int patch_info_offset() { return _patch_info_offset; }
506
507 PatchingStub(MacroAssembler* masm, PatchID id, int index = -1):
508 _id(id)
509 , _info(nullptr)
510 , _index(index) {
511 // force alignment of patch sites so we
512 // can guarantee atomic writes to the patch site.
513 align_patch_site(masm);
514 _pc_start = masm->pc();
515 masm->bind(_patch_site_entry);
516 }
517
518 virtual int nr_immediate_oops_patched() const {
519 if (_id == load_mirror_id || _id == load_appendix_id) {
520 return 1;
521 }
522 return 0;
523 }
524
525 void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
526 _info = info;
527 _obj = obj;
528 masm->bind(_patch_site_continuation);
529 _bytes_to_copy = pointer_delta_as_int(masm->pc(), pc_start());
530 if (_id == PatchingStub::access_field_id) {
531 // embed a fixed offset to handle long patches which need to be offset by a word.
532 // the patching code will just add the field offset field to this offset so
533 // that we can reference either the high or low word of a double word field.
534 int field_offset = 0;
535 switch (patch_code) {
536 case lir_patch_low: field_offset = lo_word_offset_in_bytes; break;
537 case lir_patch_high: field_offset = hi_word_offset_in_bytes; break;
538 case lir_patch_normal: field_offset = 0; break;
539 default: ShouldNotReachHere();
540 }
541 NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());
542 n_move->set_offset(field_offset);
543 // Copy will never get executed, so only copy the part which is required for patching.
544 _bytes_to_copy = MAX2(n_move->num_bytes_to_end_of_patch(), (int)NativeGeneralJump::instruction_size);
545 } else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {
546 assert(_obj != noreg, "must have register object for load_klass/load_mirror");
547 #ifdef ASSERT
548 // verify that we're pointing at a NativeMovConstReg
549 nativeMovConstReg_at(pc_start());
550 #endif
551 } else {
552 ShouldNotReachHere();
553 }
554 assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");
555 }
556
557 address pc_start() const { return _pc_start; }
558 PatchID id() const { return _id; }
559
560 virtual void emit_code(LIR_Assembler* e);
561 virtual CodeEmitInfo* info() const { return _info; }
562 virtual void visit(LIR_OpVisitState* visitor) {
563 visitor->do_slow_case(_info);
564 }
565 #ifndef PRODUCT
566 virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }
567 #endif // PRODUCT
568 };
569
570
571 //------------------------------------------------------------------------------
572 // DeoptimizeStub
573 //
574 class DeoptimizeStub : public CodeStub {
575 private:
576 CodeEmitInfo* _info;
577 jint _trap_request;
578
579 public:
580 DeoptimizeStub(CodeEmitInfo* info, Deoptimization::DeoptReason reason, Deoptimization::DeoptAction action) :
581 _info(new CodeEmitInfo(info)), _trap_request(Deoptimization::make_trap_request(reason, action)) {
582 FrameMap* f = Compilation::current()->frame_map();
583 f->update_reserved_argument_area_size(2 * BytesPerWord);
584 }
585
586 virtual void emit_code(LIR_Assembler* e);
587 virtual CodeEmitInfo* info() const { return _info; }
588 virtual bool is_exception_throw_stub() const { return true; }
589 virtual void visit(LIR_OpVisitState* visitor) {
590 visitor->do_slow_case(_info);
591 }
592 #ifndef PRODUCT
593 virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }
594 #endif // PRODUCT
595 };
596
597
598 class SimpleExceptionStub: public CodeStub {
599 private:
600 LIR_Opr _obj;
601 StubId _stub;
602 CodeEmitInfo* _info;
603
604 public:
605 SimpleExceptionStub(StubId stub, LIR_Opr obj, CodeEmitInfo* info):
606 _obj(obj), _stub(stub), _info(info) {
607 FrameMap* f = Compilation::current()->frame_map();
608 f->update_reserved_argument_area_size(2 * BytesPerWord);
609 }
610
611 void set_obj(LIR_Opr obj) {
612 _obj = obj;
613 }
614
615 virtual void emit_code(LIR_Assembler* e);
616 virtual CodeEmitInfo* info() const { return _info; }
617 virtual bool is_exception_throw_stub() const { return true; }
618 virtual bool is_simple_exception_stub() const { return true; }
619 virtual void visit(LIR_OpVisitState* visitor) {
620 if (_obj->is_valid()) visitor->do_input(_obj);
621 visitor->do_slow_case(_info);
622 }
623 #ifndef PRODUCT
624 virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }
625 #endif // PRODUCT
626 };
627
628
629
630 class ArrayStoreExceptionStub: public SimpleExceptionStub {
631 public:
632 ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(StubId::c1_throw_array_store_exception_id, obj, info) {}
633 #ifndef PRODUCT
634 virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }
635 #endif // PRODUCT
636 };
637
638
639 class ArrayCopyStub: public CodeStub {
640 private:
641 LIR_OpArrayCopy* _op;
642
643 public:
644 ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) {
645 FrameMap* f = Compilation::current()->frame_map();
646 f->update_reserved_argument_area_size(arraycopystub_reserved_argument_area_size * BytesPerWord);
647 }
648
649 LIR_Opr src() const { return _op->src(); }
650 LIR_Opr src_pos() const { return _op->src_pos(); }
651 LIR_Opr dst() const { return _op->dst(); }
652 LIR_Opr dst_pos() const { return _op->dst_pos(); }
653 LIR_Opr length() const { return _op->length(); }
654 LIR_Opr tmp() const { return _op->tmp(); }
655
656 virtual void emit_code(LIR_Assembler* e);
657 virtual CodeEmitInfo* info() const { return _op->info(); }
658 virtual void visit(LIR_OpVisitState* visitor) {
659 // don't pass in the code emit info since it's processed in the fast path
660 visitor->do_slow_case();
661 }
662 #ifndef PRODUCT
663 virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }
664 #endif // PRODUCT
665 };
666
667 #endif // SHARE_C1_C1_CODESTUBS_HPP