Path: blob/master/src/hotspot/share/c1/c1_CodeStubs.hpp
40930 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_C1_C1_CODESTUBS_HPP25#define SHARE_C1_C1_CODESTUBS_HPP2627#include "c1/c1_FrameMap.hpp"28#include "c1/c1_IR.hpp"29#include "c1/c1_Instruction.hpp"30#include "c1/c1_LIR.hpp"31#include "c1/c1_Runtime1.hpp"32#include "code/nativeInst.hpp"33#include "utilities/growableArray.hpp"34#include "utilities/macros.hpp"3536class CodeEmitInfo;37class LIR_Assembler;38class LIR_OpVisitState;3940// CodeStubs are little 'out-of-line' pieces of code that41// usually handle slow cases of operations. All code stubs42// are collected and code is emitted at the end of the43// nmethod.4445class CodeStub: public CompilationResourceObj {46protected:47Label _entry; // label at the stub entry point48Label _continuation; // label where stub continues, if any4950public:51CodeStub() {}5253// code generation54void assert_no_unbound_labels() { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); }55virtual void emit_code(LIR_Assembler* e) = 0;56virtual CodeEmitInfo* info() const { return NULL; }57virtual bool is_exception_throw_stub() const { return false; }58virtual bool is_range_check_stub() const { return false; }59virtual bool is_divbyzero_stub() const { return false; }60virtual bool is_simple_exception_stub() const { return false; }61#ifndef PRODUCT62virtual void print_name(outputStream* out) const = 0;63#endif6465// label access66Label* entry() { return &_entry; }67Label* continuation() { return &_continuation; }68// for LIR69virtual void visit(LIR_OpVisitState* visit) {70#ifndef PRODUCT71if (LIRTracePeephole && Verbose) {72tty->print("no visitor for ");73print_name(tty);74tty->cr();75}76#endif77}78};7980class CodeStubList: public GrowableArray<CodeStub*> {81public:82CodeStubList(): GrowableArray<CodeStub*>() {}8384void append(CodeStub* stub) {85if (!contains(stub)) {86GrowableArray<CodeStub*>::append(stub);87}88}89};9091class C1SafepointPollStub: public CodeStub {92private:93uintptr_t _safepoint_offset;9495public:96C1SafepointPollStub() :97_safepoint_offset(0) {98}99100uintptr_t safepoint_offset() { return _safepoint_offset; }101void set_safepoint_offset(uintptr_t safepoint_offset) { _safepoint_offset = safepoint_offset; }102103virtual void emit_code(LIR_Assembler* e);104virtual void visit(LIR_OpVisitState* visitor) {105// don't pass in the code emit info since it's processed in the fast path106visitor->do_slow_case();107}108#ifndef PRODUCT109virtual void print_name(outputStream* out) const { out->print("C1SafepointPollStub"); }110#endif // PRODUCT111};112113class CounterOverflowStub: public CodeStub {114private:115CodeEmitInfo* _info;116int _bci;117LIR_Opr _method;118119public:120CounterOverflowStub(CodeEmitInfo* info, int bci, LIR_Opr method) : _info(info), _bci(bci), _method(method) {121}122123virtual void emit_code(LIR_Assembler* e);124125virtual void visit(LIR_OpVisitState* visitor) {126visitor->do_slow_case(_info);127visitor->do_input(_method);128}129130#ifndef PRODUCT131virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); }132#endif // PRODUCT133134};135136class ConversionStub: public CodeStub {137private:138Bytecodes::Code _bytecode;139LIR_Opr _input;140LIR_Opr _result;141142static float float_zero;143static double double_zero;144public:145ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result)146: _bytecode(bytecode), _input(input), _result(result) {147NOT_IA32( ShouldNotReachHere(); ) // used only on x86-32148}149150Bytecodes::Code bytecode() { return _bytecode; }151LIR_Opr input() { return _input; }152LIR_Opr result() { return _result; }153154virtual void emit_code(LIR_Assembler* e);155virtual void visit(LIR_OpVisitState* visitor) {156visitor->do_slow_case();157visitor->do_input(_input);158visitor->do_output(_result);159}160#ifndef PRODUCT161virtual void print_name(outputStream* out) const { out->print("ConversionStub"); }162#endif // PRODUCT163};164165166// Throws ArrayIndexOutOfBoundsException by default but can be167// configured to throw IndexOutOfBoundsException in constructor168class RangeCheckStub: public CodeStub {169private:170CodeEmitInfo* _info;171LIR_Opr _index;172LIR_Opr _array;173bool _throw_index_out_of_bounds_exception;174175public:176// For ArrayIndexOutOfBoundsException.177RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array);178// For IndexOutOfBoundsException.179RangeCheckStub(CodeEmitInfo* info, LIR_Opr index);180virtual void emit_code(LIR_Assembler* e);181virtual CodeEmitInfo* info() const { return _info; }182virtual bool is_exception_throw_stub() const { return true; }183virtual bool is_range_check_stub() const { return true; }184virtual void visit(LIR_OpVisitState* visitor) {185visitor->do_slow_case(_info);186visitor->do_input(_index);187if (_array) { visitor->do_input(_array); }188}189#ifndef PRODUCT190virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); }191#endif // PRODUCT192};193194// stub used when predicate fails and deoptimization is needed195class PredicateFailedStub: public CodeStub {196private:197CodeEmitInfo* _info;198199public:200PredicateFailedStub(CodeEmitInfo* info);201virtual void emit_code(LIR_Assembler* e);202virtual CodeEmitInfo* info() const { return _info; }203virtual void visit(LIR_OpVisitState* visitor) {204visitor->do_slow_case(_info);205}206#ifndef PRODUCT207virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); }208#endif // PRODUCT209};210211class DivByZeroStub: public CodeStub {212private:213CodeEmitInfo* _info;214int _offset;215216public:217DivByZeroStub(CodeEmitInfo* info)218: _info(info), _offset(-1) {219}220DivByZeroStub(int offset, CodeEmitInfo* info)221: _info(info), _offset(offset) {222}223virtual void emit_code(LIR_Assembler* e);224virtual CodeEmitInfo* info() const { return _info; }225virtual bool is_exception_throw_stub() const { return true; }226virtual bool is_divbyzero_stub() const { return true; }227virtual void visit(LIR_OpVisitState* visitor) {228visitor->do_slow_case(_info);229}230#ifndef PRODUCT231virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); }232#endif // PRODUCT233};234235236class ImplicitNullCheckStub: public CodeStub {237private:238CodeEmitInfo* _info;239int _offset;240241public:242ImplicitNullCheckStub(int offset, CodeEmitInfo* info)243: _info(info), _offset(offset) {244}245virtual void emit_code(LIR_Assembler* e);246virtual CodeEmitInfo* info() const { return _info; }247virtual bool is_exception_throw_stub() const { return true; }248virtual void visit(LIR_OpVisitState* visitor) {249visitor->do_slow_case(_info);250}251#ifndef PRODUCT252virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); }253#endif // PRODUCT254};255256257class NewInstanceStub: public CodeStub {258private:259ciInstanceKlass* _klass;260LIR_Opr _klass_reg;261LIR_Opr _result;262CodeEmitInfo* _info;263Runtime1::StubID _stub_id;264265public:266NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id);267virtual void emit_code(LIR_Assembler* e);268virtual CodeEmitInfo* info() const { return _info; }269virtual void visit(LIR_OpVisitState* visitor) {270visitor->do_slow_case(_info);271visitor->do_input(_klass_reg);272visitor->do_output(_result);273}274#ifndef PRODUCT275virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); }276#endif // PRODUCT277};278279280class NewTypeArrayStub: public CodeStub {281private:282LIR_Opr _klass_reg;283LIR_Opr _length;284LIR_Opr _result;285CodeEmitInfo* _info;286287public:288NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);289virtual void emit_code(LIR_Assembler* e);290virtual CodeEmitInfo* info() const { return _info; }291virtual void visit(LIR_OpVisitState* visitor) {292visitor->do_slow_case(_info);293visitor->do_input(_klass_reg);294visitor->do_input(_length);295assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);296}297#ifndef PRODUCT298virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); }299#endif // PRODUCT300};301302303class NewObjectArrayStub: public CodeStub {304private:305LIR_Opr _klass_reg;306LIR_Opr _length;307LIR_Opr _result;308CodeEmitInfo* _info;309310public:311NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);312virtual void emit_code(LIR_Assembler* e);313virtual CodeEmitInfo* info() const { return _info; }314virtual void visit(LIR_OpVisitState* visitor) {315visitor->do_slow_case(_info);316visitor->do_input(_klass_reg);317visitor->do_input(_length);318assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);319}320#ifndef PRODUCT321virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); }322#endif // PRODUCT323};324325326class MonitorAccessStub: public CodeStub {327protected:328LIR_Opr _obj_reg;329LIR_Opr _lock_reg;330331public:332MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) {333_obj_reg = obj_reg;334_lock_reg = lock_reg;335}336337#ifndef PRODUCT338virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); }339#endif // PRODUCT340};341342343class MonitorEnterStub: public MonitorAccessStub {344private:345CodeEmitInfo* _info;346347public:348MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info);349350virtual void emit_code(LIR_Assembler* e);351virtual CodeEmitInfo* info() const { return _info; }352virtual void visit(LIR_OpVisitState* visitor) {353visitor->do_input(_obj_reg);354visitor->do_input(_lock_reg);355visitor->do_slow_case(_info);356}357#ifndef PRODUCT358virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); }359#endif // PRODUCT360};361362363class MonitorExitStub: public MonitorAccessStub {364private:365bool _compute_lock;366int _monitor_ix;367368public:369MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix)370: MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),371_compute_lock(compute_lock), _monitor_ix(monitor_ix) { }372virtual void emit_code(LIR_Assembler* e);373virtual void visit(LIR_OpVisitState* visitor) {374assert(_obj_reg->is_illegal(), "unused");375if (_compute_lock) {376visitor->do_temp(_lock_reg);377} else {378visitor->do_input(_lock_reg);379}380}381#ifndef PRODUCT382virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }383#endif // PRODUCT384};385386387class PatchingStub: public CodeStub {388public:389enum PatchID {390access_field_id,391load_klass_id,392load_mirror_id,393load_appendix_id394};395enum constants {396patch_info_size = 3397};398private:399PatchID _id;400address _pc_start;401int _bytes_to_copy;402Label _patched_code_entry;403Label _patch_site_entry;404Label _patch_site_continuation;405Register _obj;406CodeEmitInfo* _info;407int _index; // index of the patchable oop or Klass* in nmethod or metadata table if needed408static int _patch_info_offset;409410void align_patch_site(MacroAssembler* masm);411412public:413static int patch_info_offset() { return _patch_info_offset; }414415PatchingStub(MacroAssembler* masm, PatchID id, int index = -1):416_id(id)417, _info(NULL)418, _index(index) {419// force alignment of patch sites so we420// can guarantee atomic writes to the patch site.421align_patch_site(masm);422_pc_start = masm->pc();423masm->bind(_patch_site_entry);424}425426void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {427_info = info;428_obj = obj;429masm->bind(_patch_site_continuation);430_bytes_to_copy = masm->pc() - pc_start();431if (_id == PatchingStub::access_field_id) {432// embed a fixed offset to handle long patches which need to be offset by a word.433// the patching code will just add the field offset field to this offset so434// that we can reference either the high or low word of a double word field.435int field_offset = 0;436switch (patch_code) {437case lir_patch_low: field_offset = lo_word_offset_in_bytes; break;438case lir_patch_high: field_offset = hi_word_offset_in_bytes; break;439case lir_patch_normal: field_offset = 0; break;440default: ShouldNotReachHere();441}442NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());443n_move->set_offset(field_offset);444// Copy will never get executed, so only copy the part which is required for patching.445_bytes_to_copy = MAX2(n_move->num_bytes_to_end_of_patch(), (int)NativeGeneralJump::instruction_size);446} else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {447assert(_obj != noreg, "must have register object for load_klass/load_mirror");448#ifdef ASSERT449// verify that we're pointing at a NativeMovConstReg450nativeMovConstReg_at(pc_start());451#endif452} else {453ShouldNotReachHere();454}455assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");456}457458address pc_start() const { return _pc_start; }459PatchID id() const { return _id; }460461virtual void emit_code(LIR_Assembler* e);462virtual CodeEmitInfo* info() const { return _info; }463virtual void visit(LIR_OpVisitState* visitor) {464visitor->do_slow_case(_info);465}466#ifndef PRODUCT467virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }468#endif // PRODUCT469};470471472//------------------------------------------------------------------------------473// DeoptimizeStub474//475class DeoptimizeStub : public CodeStub {476private:477CodeEmitInfo* _info;478jint _trap_request;479480public:481DeoptimizeStub(CodeEmitInfo* info, Deoptimization::DeoptReason reason, Deoptimization::DeoptAction action) :482_info(new CodeEmitInfo(info)), _trap_request(Deoptimization::make_trap_request(reason, action)) {}483484virtual void emit_code(LIR_Assembler* e);485virtual CodeEmitInfo* info() const { return _info; }486virtual bool is_exception_throw_stub() const { return true; }487virtual void visit(LIR_OpVisitState* visitor) {488visitor->do_slow_case(_info);489}490#ifndef PRODUCT491virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }492#endif // PRODUCT493};494495496class SimpleExceptionStub: public CodeStub {497private:498LIR_Opr _obj;499Runtime1::StubID _stub;500CodeEmitInfo* _info;501502public:503SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info):504_obj(obj), _stub(stub), _info(info) {505}506507void set_obj(LIR_Opr obj) {508_obj = obj;509}510511virtual void emit_code(LIR_Assembler* e);512virtual CodeEmitInfo* info() const { return _info; }513virtual bool is_exception_throw_stub() const { return true; }514virtual bool is_simple_exception_stub() const { return true; }515virtual void visit(LIR_OpVisitState* visitor) {516if (_obj->is_valid()) visitor->do_input(_obj);517visitor->do_slow_case(_info);518}519#ifndef PRODUCT520virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }521#endif // PRODUCT522};523524525526class ArrayStoreExceptionStub: public SimpleExceptionStub {527private:528CodeEmitInfo* _info;529530public:531ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {}532#ifndef PRODUCT533virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }534#endif // PRODUCT535};536537538class ArrayCopyStub: public CodeStub {539private:540LIR_OpArrayCopy* _op;541542public:543ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { }544545LIR_Opr src() const { return _op->src(); }546LIR_Opr src_pos() const { return _op->src_pos(); }547LIR_Opr dst() const { return _op->dst(); }548LIR_Opr dst_pos() const { return _op->dst_pos(); }549LIR_Opr length() const { return _op->length(); }550LIR_Opr tmp() const { return _op->tmp(); }551552virtual void emit_code(LIR_Assembler* e);553virtual CodeEmitInfo* info() const { return _op->info(); }554virtual void visit(LIR_OpVisitState* visitor) {555// don't pass in the code emit info since it's processed in the fast path556visitor->do_slow_case();557}558#ifndef PRODUCT559virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }560#endif // PRODUCT561};562563#endif // SHARE_C1_C1_CODESTUBS_HPP564565566