aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_C1_C1_CODESTUBS_HPP aoqi@0: #define SHARE_VM_C1_C1_CODESTUBS_HPP aoqi@0: aoqi@0: #include "c1/c1_FrameMap.hpp" aoqi@0: #include "c1/c1_IR.hpp" aoqi@0: #include "c1/c1_Instruction.hpp" aoqi@0: #include "c1/c1_LIR.hpp" aoqi@0: #include "c1/c1_Runtime1.hpp" aoqi@0: #include "utilities/array.hpp" aoqi@0: #include "utilities/macros.hpp" aoqi@0: aoqi@0: class CodeEmitInfo; aoqi@0: class LIR_Assembler; aoqi@0: class LIR_OpVisitState; aoqi@0: aoqi@0: // CodeStubs are little 'out-of-line' pieces of code that aoqi@0: // usually handle slow cases of operations. All code stubs aoqi@0: // are collected and code is emitted at the end of the aoqi@0: // nmethod. aoqi@0: aoqi@0: class CodeStub: public CompilationResourceObj { aoqi@0: protected: aoqi@0: Label _entry; // label at the stub entry point aoqi@0: Label _continuation; // label where stub continues, if any aoqi@0: aoqi@0: public: aoqi@0: CodeStub() {} aoqi@0: aoqi@0: // code generation aoqi@0: void assert_no_unbound_labels() { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); } aoqi@0: virtual void emit_code(LIR_Assembler* e) = 0; aoqi@0: virtual CodeEmitInfo* info() const { return NULL; } aoqi@0: virtual bool is_exception_throw_stub() const { return false; } aoqi@0: virtual bool is_range_check_stub() const { return false; } aoqi@0: virtual bool is_divbyzero_stub() const { return false; } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const = 0; aoqi@0: #endif aoqi@0: aoqi@0: // label access aoqi@0: Label* entry() { return &_entry; } aoqi@0: Label* continuation() { return &_continuation; } aoqi@0: // for LIR aoqi@0: virtual void visit(LIR_OpVisitState* visit) { aoqi@0: #ifndef PRODUCT aoqi@0: if (LIRTracePeephole && Verbose) { aoqi@0: tty->print("no visitor for "); aoqi@0: print_name(tty); aoqi@0: tty->cr(); aoqi@0: } aoqi@0: #endif aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: define_array(CodeStubArray, CodeStub*) aoqi@0: define_stack(_CodeStubList, CodeStubArray) aoqi@0: aoqi@0: class CodeStubList: public _CodeStubList { aoqi@0: public: aoqi@0: CodeStubList(): _CodeStubList() {} aoqi@0: aoqi@0: void append(CodeStub* stub) { aoqi@0: if (!contains(stub)) { aoqi@0: _CodeStubList::append(stub); aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: class CounterOverflowStub: public CodeStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: int _bci; aoqi@0: LIR_Opr _method; aoqi@0: aoqi@0: public: aoqi@0: CounterOverflowStub(CodeEmitInfo* info, int bci, LIR_Opr method) : _info(info), _bci(bci), _method(method) { aoqi@0: } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: visitor->do_input(_method); aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); } aoqi@0: #endif // PRODUCT aoqi@0: aoqi@0: }; aoqi@0: aoqi@0: class ConversionStub: public CodeStub { aoqi@0: private: aoqi@0: Bytecodes::Code _bytecode; aoqi@0: LIR_Opr _input; aoqi@0: LIR_Opr _result; aoqi@0: aoqi@0: static float float_zero; aoqi@0: static double double_zero; aoqi@0: public: aoqi@0: ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result) aoqi@0: : _bytecode(bytecode), _input(input), _result(result) { aoqi@0: } aoqi@0: aoqi@0: Bytecodes::Code bytecode() { return _bytecode; } aoqi@0: LIR_Opr input() { return _input; } aoqi@0: LIR_Opr result() { return _result; } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(); aoqi@0: visitor->do_input(_input); aoqi@0: visitor->do_output(_result); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("ConversionStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: // Throws ArrayIndexOutOfBoundsException by default but can be aoqi@0: // configured to throw IndexOutOfBoundsException in constructor aoqi@0: class RangeCheckStub: public CodeStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: LIR_Opr _index; aoqi@0: bool _throw_index_out_of_bounds_exception; aoqi@0: aoqi@0: public: aoqi@0: RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, bool throw_index_out_of_bounds_exception = false); aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual bool is_exception_throw_stub() const { return true; } aoqi@0: virtual bool is_range_check_stub() const { return true; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: visitor->do_input(_index); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: // stub used when predicate fails and deoptimization is needed aoqi@0: class PredicateFailedStub: public CodeStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: PredicateFailedStub(CodeEmitInfo* info); aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: class DivByZeroStub: public CodeStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: int _offset; aoqi@0: aoqi@0: public: aoqi@0: DivByZeroStub(CodeEmitInfo* info) aoqi@0: : _info(info), _offset(-1) { aoqi@0: } aoqi@0: DivByZeroStub(int offset, CodeEmitInfo* info) aoqi@0: : _info(info), _offset(offset) { aoqi@0: } aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual bool is_exception_throw_stub() const { return true; } aoqi@0: virtual bool is_divbyzero_stub() const { return true; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class ImplicitNullCheckStub: public CodeStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: int _offset; aoqi@0: aoqi@0: public: aoqi@0: ImplicitNullCheckStub(int offset, CodeEmitInfo* info) aoqi@0: : _offset(offset), _info(info) { aoqi@0: } aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual bool is_exception_throw_stub() const { return true; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class NewInstanceStub: public CodeStub { aoqi@0: private: aoqi@0: ciInstanceKlass* _klass; aoqi@0: LIR_Opr _klass_reg; aoqi@0: LIR_Opr _result; aoqi@0: CodeEmitInfo* _info; aoqi@0: Runtime1::StubID _stub_id; aoqi@0: aoqi@0: public: aoqi@0: NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id); aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: visitor->do_input(_klass_reg); aoqi@0: visitor->do_output(_result); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class NewTypeArrayStub: public CodeStub { aoqi@0: private: aoqi@0: LIR_Opr _klass_reg; aoqi@0: LIR_Opr _length; aoqi@0: LIR_Opr _result; aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info); aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: visitor->do_input(_klass_reg); aoqi@0: visitor->do_input(_length); aoqi@0: assert(_result->is_valid(), "must be valid"); visitor->do_output(_result); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class NewObjectArrayStub: public CodeStub { aoqi@0: private: aoqi@0: LIR_Opr _klass_reg; aoqi@0: LIR_Opr _length; aoqi@0: LIR_Opr _result; aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info); aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: visitor->do_input(_klass_reg); aoqi@0: visitor->do_input(_length); aoqi@0: assert(_result->is_valid(), "must be valid"); visitor->do_output(_result); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class MonitorAccessStub: public CodeStub { aoqi@0: protected: aoqi@0: LIR_Opr _obj_reg; aoqi@0: LIR_Opr _lock_reg; aoqi@0: aoqi@0: public: aoqi@0: MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) { aoqi@0: _obj_reg = obj_reg; aoqi@0: _lock_reg = lock_reg; aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class MonitorEnterStub: public MonitorAccessStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info); aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_input(_obj_reg); aoqi@0: visitor->do_input(_lock_reg); aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class MonitorExitStub: public MonitorAccessStub { aoqi@0: private: aoqi@0: bool _compute_lock; aoqi@0: int _monitor_ix; aoqi@0: aoqi@0: public: aoqi@0: MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix) aoqi@0: : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg), aoqi@0: _compute_lock(compute_lock), _monitor_ix(monitor_ix) { } aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: assert(_obj_reg->is_illegal(), "unused"); aoqi@0: if (_compute_lock) { aoqi@0: visitor->do_temp(_lock_reg); aoqi@0: } else { aoqi@0: visitor->do_input(_lock_reg); aoqi@0: } aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class PatchingStub: public CodeStub { aoqi@0: public: aoqi@0: enum PatchID { aoqi@0: access_field_id, aoqi@0: load_klass_id, aoqi@0: load_mirror_id, aoqi@0: load_appendix_id aoqi@0: }; aoqi@0: enum constants { aoqi@0: patch_info_size = 3 aoqi@0: }; aoqi@0: private: aoqi@0: PatchID _id; aoqi@0: address _pc_start; aoqi@0: int _bytes_to_copy; aoqi@0: Label _patched_code_entry; aoqi@0: Label _patch_site_entry; aoqi@0: Label _patch_site_continuation; aoqi@0: Register _obj; aoqi@0: CodeEmitInfo* _info; aoqi@0: int _index; // index of the patchable oop or Klass* in nmethod oop or metadata table if needed aoqi@0: static int _patch_info_offset; aoqi@0: aoqi@0: void align_patch_site(MacroAssembler* masm); aoqi@0: aoqi@0: public: aoqi@0: static int patch_info_offset() { return _patch_info_offset; } aoqi@0: aoqi@0: PatchingStub(MacroAssembler* masm, PatchID id, int index = -1): aoqi@0: _id(id) aoqi@0: , _info(NULL) aoqi@0: , _index(index) { aoqi@0: if (os::is_MP()) { aoqi@0: // force alignment of patch sites on MP hardware so we aoqi@0: // can guarantee atomic writes to the patch site. aoqi@0: align_patch_site(masm); aoqi@0: } aoqi@0: _pc_start = masm->pc(); aoqi@0: masm->bind(_patch_site_entry); aoqi@0: } aoqi@0: aoqi@0: void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) { aoqi@0: _info = info; aoqi@0: _obj = obj; aoqi@0: masm->bind(_patch_site_continuation); aoqi@0: _bytes_to_copy = masm->pc() - pc_start(); aoqi@0: if (_id == PatchingStub::access_field_id) { aoqi@0: // embed a fixed offset to handle long patches which need to be offset by a word. aoqi@0: // the patching code will just add the field offset field to this offset so aoqi@0: // that we can refernce either the high or low word of a double word field. aoqi@0: int field_offset = 0; aoqi@0: switch (patch_code) { aoqi@0: case lir_patch_low: field_offset = lo_word_offset_in_bytes; break; aoqi@0: case lir_patch_high: field_offset = hi_word_offset_in_bytes; break; aoqi@0: case lir_patch_normal: field_offset = 0; break; aoqi@0: default: ShouldNotReachHere(); aoqi@0: } aoqi@0: NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start()); aoqi@0: n_move->set_offset(field_offset); aoqi@0: } else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) { aoqi@0: assert(_obj != noreg, "must have register object for load_klass/load_mirror"); aoqi@0: #ifdef ASSERT aoqi@0: // verify that we're pointing at a NativeMovConstReg aoqi@0: nativeMovConstReg_at(pc_start()); aoqi@0: #endif aoqi@0: } else { aoqi@0: ShouldNotReachHere(); aoqi@0: } aoqi@0: assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes"); aoqi@0: } aoqi@0: aoqi@0: address pc_start() const { return _pc_start; } aoqi@0: PatchID id() const { return _id; } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("PatchingStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: //------------------------------------------------------------------------------ aoqi@0: // DeoptimizeStub aoqi@0: // aoqi@0: class DeoptimizeStub : public CodeStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {} aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual bool is_exception_throw_stub() const { return true; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class SimpleExceptionStub: public CodeStub { aoqi@0: private: aoqi@0: LIR_Opr _obj; aoqi@0: Runtime1::StubID _stub; aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info): aoqi@0: _obj(obj), _info(info), _stub(stub) { aoqi@0: } aoqi@0: aoqi@0: void set_obj(LIR_Opr obj) { aoqi@0: _obj = obj; aoqi@0: } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _info; } aoqi@0: virtual bool is_exception_throw_stub() const { return true; } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: if (_obj->is_valid()) visitor->do_input(_obj); aoqi@0: visitor->do_slow_case(_info); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: aoqi@0: class ArrayStoreExceptionStub: public SimpleExceptionStub { aoqi@0: private: aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {} aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: class ArrayCopyStub: public CodeStub { aoqi@0: private: aoqi@0: LIR_OpArrayCopy* _op; aoqi@0: aoqi@0: public: aoqi@0: ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { } aoqi@0: aoqi@0: LIR_Opr src() const { return _op->src(); } aoqi@0: LIR_Opr src_pos() const { return _op->src_pos(); } aoqi@0: LIR_Opr dst() const { return _op->dst(); } aoqi@0: LIR_Opr dst_pos() const { return _op->dst_pos(); } aoqi@0: LIR_Opr length() const { return _op->length(); } aoqi@0: LIR_Opr tmp() const { return _op->tmp(); } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual CodeEmitInfo* info() const { return _op->info(); } aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: // don't pass in the code emit info since it's processed in the fast path aoqi@0: visitor->do_slow_case(); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: ////////////////////////////////////////////////////////////////////////////////////////// aoqi@0: #if INCLUDE_ALL_GCS aoqi@0: aoqi@0: // Code stubs for Garbage-First barriers. aoqi@0: class G1PreBarrierStub: public CodeStub { aoqi@0: private: aoqi@0: bool _do_load; aoqi@0: LIR_Opr _addr; aoqi@0: LIR_Opr _pre_val; aoqi@0: LIR_PatchCode _patch_code; aoqi@0: CodeEmitInfo* _info; aoqi@0: aoqi@0: public: aoqi@0: // Version that _does_ generate a load of the previous value from addr. aoqi@0: // addr (the address of the field to be read) must be a LIR_Address aoqi@0: // pre_val (a temporary register) must be a register; aoqi@0: G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : aoqi@0: _addr(addr), _pre_val(pre_val), _do_load(true), aoqi@0: _patch_code(patch_code), _info(info) aoqi@0: { aoqi@0: assert(_pre_val->is_register(), "should be temporary register"); aoqi@0: assert(_addr->is_address(), "should be the address of the field"); aoqi@0: } aoqi@0: aoqi@0: // Version that _does not_ generate load of the previous value; the aoqi@0: // previous value is assumed to have already been loaded into pre_val. aoqi@0: G1PreBarrierStub(LIR_Opr pre_val) : aoqi@0: _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false), aoqi@0: _patch_code(lir_patch_none), _info(NULL) aoqi@0: { aoqi@0: assert(_pre_val->is_register(), "should be a register"); aoqi@0: } aoqi@0: aoqi@0: LIR_Opr addr() const { return _addr; } aoqi@0: LIR_Opr pre_val() const { return _pre_val; } aoqi@0: LIR_PatchCode patch_code() const { return _patch_code; } aoqi@0: CodeEmitInfo* info() const { return _info; } aoqi@0: bool do_load() const { return _do_load; } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: if (_do_load) { aoqi@0: // don't pass in the code emit info since it's processed in the fast aoqi@0: // path aoqi@0: if (_info != NULL) aoqi@0: visitor->do_slow_case(_info); aoqi@0: else aoqi@0: visitor->do_slow_case(); aoqi@0: aoqi@0: visitor->do_input(_addr); aoqi@0: visitor->do_temp(_pre_val); aoqi@0: } else { aoqi@0: visitor->do_slow_case(); aoqi@0: visitor->do_input(_pre_val); aoqi@0: } aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: class G1PostBarrierStub: public CodeStub { aoqi@0: private: aoqi@0: LIR_Opr _addr; aoqi@0: LIR_Opr _new_val; aoqi@0: aoqi@0: static jbyte* _byte_map_base; aoqi@0: static jbyte* byte_map_base_slow(); aoqi@0: static jbyte* byte_map_base() { aoqi@0: if (_byte_map_base == NULL) { aoqi@0: _byte_map_base = byte_map_base_slow(); aoqi@0: } aoqi@0: return _byte_map_base; aoqi@0: } aoqi@0: aoqi@0: public: aoqi@0: // addr (the address of the object head) and new_val must be registers. aoqi@0: G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { } aoqi@0: aoqi@0: LIR_Opr addr() const { return _addr; } aoqi@0: LIR_Opr new_val() const { return _new_val; } aoqi@0: aoqi@0: virtual void emit_code(LIR_Assembler* e); aoqi@0: virtual void visit(LIR_OpVisitState* visitor) { aoqi@0: // don't pass in the code emit info since it's processed in the fast path aoqi@0: visitor->do_slow_case(); aoqi@0: visitor->do_input(_addr); aoqi@0: visitor->do_input(_new_val); aoqi@0: } aoqi@0: #ifndef PRODUCT aoqi@0: virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); } aoqi@0: #endif // PRODUCT aoqi@0: }; aoqi@0: aoqi@0: #endif // INCLUDE_ALL_GCS aoqi@0: ////////////////////////////////////////////////////////////////////////////////////////// aoqi@0: aoqi@0: #endif // SHARE_VM_C1_C1_CODESTUBS_HPP