1 /*
  2  * Copyright (c) 1999, 2024, 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_IR.hpp"
 30 #include "c1/c1_Instruction.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   C1StubId         _stub_id;
345 
346  public:
347   NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId 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   bool _compute_lock;
463   int  _monitor_ix;
464 
465  public:
466   MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix)
467     : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),
468       _compute_lock(compute_lock), _monitor_ix(monitor_ix) { }
469   virtual void emit_code(LIR_Assembler* e);
470   virtual void visit(LIR_OpVisitState* visitor) {
471     assert(_obj_reg->is_illegal(), "unused");
472     if (_compute_lock) {
473       visitor->do_temp(_lock_reg);
474     } else {
475       visitor->do_input(_lock_reg);
476     }
477   }
478 #ifndef PRODUCT
479   virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }
480 #endif // PRODUCT
481 };
482 
483 
484 class PatchingStub: public CodeStub {
485  public:
486   enum PatchID {
487     access_field_id,
488     load_klass_id,
489     load_mirror_id,
490     load_appendix_id
491   };
492   enum constants {
493     patch_info_size = 3
494   };
495  private:
496   PatchID       _id;
497   address       _pc_start;
498   int           _bytes_to_copy;
499   Label         _patched_code_entry;
500   Label         _patch_site_entry;
501   Label         _patch_site_continuation;
502   Register      _obj;
503   CodeEmitInfo* _info;
504   int           _index;  // index of the patchable oop or Klass* in nmethod or metadata table if needed
505   static int    _patch_info_offset;
506 
507   void align_patch_site(MacroAssembler* masm);
508 
509  public:
510   static int patch_info_offset() { return _patch_info_offset; }
511 
512   PatchingStub(MacroAssembler* masm, PatchID id, int index = -1):
513       _id(id)
514     , _info(nullptr)
515     , _index(index) {
516     // force alignment of patch sites so we
517     // can guarantee atomic writes to the patch site.
518     align_patch_site(masm);
519     _pc_start = masm->pc();
520     masm->bind(_patch_site_entry);
521   }
522 
523   virtual int nr_immediate_oops_patched() const  {
524     if (_id == load_mirror_id || _id == load_appendix_id) {
525       return 1;
526     }
527     return 0;
528   }
529 
530   void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
531     _info = info;
532     _obj = obj;
533     masm->bind(_patch_site_continuation);
534     _bytes_to_copy = pointer_delta_as_int(masm->pc(), pc_start());
535     if (_id == PatchingStub::access_field_id) {
536       // embed a fixed offset to handle long patches which need to be offset by a word.
537       // the patching code will just add the field offset field to this offset so
538       // that we can reference either the high or low word of a double word field.
539       int field_offset = 0;
540       switch (patch_code) {
541       case lir_patch_low:         field_offset = lo_word_offset_in_bytes; break;
542       case lir_patch_high:        field_offset = hi_word_offset_in_bytes; break;
543       case lir_patch_normal:      field_offset = 0;                       break;
544       default: ShouldNotReachHere();
545       }
546       NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());
547       n_move->set_offset(field_offset);
548       // Copy will never get executed, so only copy the part which is required for patching.
549       _bytes_to_copy = MAX2(n_move->num_bytes_to_end_of_patch(), (int)NativeGeneralJump::instruction_size);
550     } else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {
551       assert(_obj != noreg, "must have register object for load_klass/load_mirror");
552 #ifdef ASSERT
553       // verify that we're pointing at a NativeMovConstReg
554       nativeMovConstReg_at(pc_start());
555 #endif
556     } else {
557       ShouldNotReachHere();
558     }
559     assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");
560   }
561 
562   address pc_start() const                       { return _pc_start; }
563   PatchID id() const                             { return _id; }
564 
565   virtual void emit_code(LIR_Assembler* e);
566   virtual CodeEmitInfo* info() const             { return _info; }
567   virtual void visit(LIR_OpVisitState* visitor) {
568     visitor->do_slow_case(_info);
569   }
570 #ifndef PRODUCT
571   virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }
572 #endif // PRODUCT
573 };
574 
575 
576 //------------------------------------------------------------------------------
577 // DeoptimizeStub
578 //
579 class DeoptimizeStub : public CodeStub {
580 private:
581   CodeEmitInfo* _info;
582   jint _trap_request;
583 
584 public:
585   DeoptimizeStub(CodeEmitInfo* info, Deoptimization::DeoptReason reason, Deoptimization::DeoptAction action) :
586     _info(new CodeEmitInfo(info)), _trap_request(Deoptimization::make_trap_request(reason, action)) {
587     FrameMap* f = Compilation::current()->frame_map();
588     f->update_reserved_argument_area_size(2 * BytesPerWord);
589   }
590 
591   virtual void emit_code(LIR_Assembler* e);
592   virtual CodeEmitInfo* info() const           { return _info; }
593   virtual bool is_exception_throw_stub() const { return true; }
594   virtual void visit(LIR_OpVisitState* visitor) {
595     visitor->do_slow_case(_info);
596   }
597 #ifndef PRODUCT
598   virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }
599 #endif // PRODUCT
600 };
601 
602 
603 class SimpleExceptionStub: public CodeStub {
604  private:
605   LIR_Opr          _obj;
606   C1StubId         _stub;
607   CodeEmitInfo*    _info;
608 
609  public:
610   SimpleExceptionStub(C1StubId stub, LIR_Opr obj, CodeEmitInfo* info):
611     _obj(obj), _stub(stub), _info(info) {
612     FrameMap* f = Compilation::current()->frame_map();
613     f->update_reserved_argument_area_size(2 * BytesPerWord);
614   }
615 
616   void set_obj(LIR_Opr obj) {
617     _obj = obj;
618   }
619 
620   virtual void emit_code(LIR_Assembler* e);
621   virtual CodeEmitInfo* info() const             { return _info; }
622   virtual bool is_exception_throw_stub() const   { return true; }
623   virtual bool is_simple_exception_stub() const  { return true; }
624   virtual void visit(LIR_OpVisitState* visitor) {
625     if (_obj->is_valid()) visitor->do_input(_obj);
626     visitor->do_slow_case(_info);
627   }
628 #ifndef PRODUCT
629   virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }
630 #endif // PRODUCT
631 };
632 
633 
634 
635 class ArrayStoreExceptionStub: public SimpleExceptionStub {
636  public:
637   ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(C1StubId::throw_array_store_exception_id, obj, info) {}
638 #ifndef PRODUCT
639   virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }
640 #endif // PRODUCT
641 };
642 
643 
644 class ArrayCopyStub: public CodeStub {
645  private:
646   LIR_OpArrayCopy* _op;
647 
648  public:
649   ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) {
650     FrameMap* f = Compilation::current()->frame_map();
651     f->update_reserved_argument_area_size(arraycopystub_reserved_argument_area_size * BytesPerWord);
652   }
653 
654   LIR_Opr src() const                         { return _op->src(); }
655   LIR_Opr src_pos() const                     { return _op->src_pos(); }
656   LIR_Opr dst() const                         { return _op->dst(); }
657   LIR_Opr dst_pos() const                     { return _op->dst_pos(); }
658   LIR_Opr length() const                      { return _op->length(); }
659   LIR_Opr tmp() const                         { return _op->tmp(); }
660 
661   virtual void emit_code(LIR_Assembler* e);
662   virtual CodeEmitInfo* info() const          { return _op->info(); }
663   virtual void visit(LIR_OpVisitState* visitor) {
664     // don't pass in the code emit info since it's processed in the fast path
665     visitor->do_slow_case();
666   }
667 #ifndef PRODUCT
668   virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }
669 #endif // PRODUCT
670 };
671 
672 #endif // SHARE_C1_C1_CODESTUBS_HPP
--- EOF ---