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 ---