Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/c1/c1_CodeStubs.hpp
32285 views
/*1* Copyright (c) 1999, 2016, 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_VM_C1_C1_CODESTUBS_HPP25#define SHARE_VM_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 "utilities/array.hpp"33#include "utilities/macros.hpp"3435class CodeEmitInfo;36class LIR_Assembler;37class LIR_OpVisitState;3839// CodeStubs are little 'out-of-line' pieces of code that40// usually handle slow cases of operations. All code stubs41// are collected and code is emitted at the end of the42// nmethod.4344class CodeStub: public CompilationResourceObj {45protected:46Label _entry; // label at the stub entry point47Label _continuation; // label where stub continues, if any4849public:50CodeStub() {}5152// code generation53void assert_no_unbound_labels() { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); }54virtual void emit_code(LIR_Assembler* e) = 0;55virtual CodeEmitInfo* info() const { return NULL; }56virtual bool is_exception_throw_stub() const { return false; }57virtual bool is_range_check_stub() const { return false; }58virtual bool is_divbyzero_stub() const { return false; }59virtual bool is_simple_exception_stub() const { return false; }60#ifndef PRODUCT61virtual void print_name(outputStream* out) const = 0;62#endif6364// label access65Label* entry() { return &_entry; }66Label* continuation() { return &_continuation; }67// for LIR68virtual void visit(LIR_OpVisitState* visit) {69#ifndef PRODUCT70if (LIRTracePeephole && Verbose) {71tty->print("no visitor for ");72print_name(tty);73tty->cr();74}75#endif76}77};787980define_array(CodeStubArray, CodeStub*)81define_stack(_CodeStubList, CodeStubArray)8283class CodeStubList: public _CodeStubList {84public:85CodeStubList(): _CodeStubList() {}8687void append(CodeStub* stub) {88if (!contains(stub)) {89_CodeStubList::append(stub);90}91}92};9394class CounterOverflowStub: public CodeStub {95private:96CodeEmitInfo* _info;97int _bci;98LIR_Opr _method;99100public:101CounterOverflowStub(CodeEmitInfo* info, int bci, LIR_Opr method) : _info(info), _bci(bci), _method(method) {102}103104virtual void emit_code(LIR_Assembler* e);105106virtual void visit(LIR_OpVisitState* visitor) {107visitor->do_slow_case(_info);108visitor->do_input(_method);109}110111#ifndef PRODUCT112virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); }113#endif // PRODUCT114115};116117class ConversionStub: public CodeStub {118private:119Bytecodes::Code _bytecode;120LIR_Opr _input;121LIR_Opr _result;122123static float float_zero;124static double double_zero;125public:126ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result)127: _bytecode(bytecode), _input(input), _result(result) {128}129130Bytecodes::Code bytecode() { return _bytecode; }131LIR_Opr input() { return _input; }132LIR_Opr result() { return _result; }133134virtual void emit_code(LIR_Assembler* e);135virtual void visit(LIR_OpVisitState* visitor) {136visitor->do_slow_case();137visitor->do_input(_input);138visitor->do_output(_result);139}140#ifndef PRODUCT141virtual void print_name(outputStream* out) const { out->print("ConversionStub"); }142#endif // PRODUCT143};144145146// Throws ArrayIndexOutOfBoundsException by default but can be147// configured to throw IndexOutOfBoundsException in constructor148class RangeCheckStub: public CodeStub {149private:150CodeEmitInfo* _info;151LIR_Opr _index;152bool _throw_index_out_of_bounds_exception;153154public:155RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, bool throw_index_out_of_bounds_exception = false);156virtual void emit_code(LIR_Assembler* e);157virtual CodeEmitInfo* info() const { return _info; }158virtual bool is_exception_throw_stub() const { return true; }159virtual bool is_range_check_stub() const { return true; }160virtual void visit(LIR_OpVisitState* visitor) {161visitor->do_slow_case(_info);162visitor->do_input(_index);163}164#ifndef PRODUCT165virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); }166#endif // PRODUCT167};168169// stub used when predicate fails and deoptimization is needed170class PredicateFailedStub: public CodeStub {171private:172CodeEmitInfo* _info;173174public:175PredicateFailedStub(CodeEmitInfo* info);176virtual void emit_code(LIR_Assembler* e);177virtual CodeEmitInfo* info() const { return _info; }178virtual void visit(LIR_OpVisitState* visitor) {179visitor->do_slow_case(_info);180}181#ifndef PRODUCT182virtual void print_name(outputStream* out) const { out->print("PredicateFailedStub"); }183#endif // PRODUCT184};185186class DivByZeroStub: public CodeStub {187private:188CodeEmitInfo* _info;189int _offset;190191public:192DivByZeroStub(CodeEmitInfo* info)193: _info(info), _offset(-1) {194}195DivByZeroStub(int offset, CodeEmitInfo* info)196: _info(info), _offset(offset) {197}198virtual void emit_code(LIR_Assembler* e);199virtual CodeEmitInfo* info() const { return _info; }200virtual bool is_exception_throw_stub() const { return true; }201virtual bool is_divbyzero_stub() const { return true; }202virtual void visit(LIR_OpVisitState* visitor) {203visitor->do_slow_case(_info);204}205#ifndef PRODUCT206virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); }207#endif // PRODUCT208};209210211class ImplicitNullCheckStub: public CodeStub {212private:213CodeEmitInfo* _info;214int _offset;215216public:217ImplicitNullCheckStub(int offset, CodeEmitInfo* info)218: _offset(offset), _info(info) {219}220virtual void emit_code(LIR_Assembler* e);221virtual CodeEmitInfo* info() const { return _info; }222virtual bool is_exception_throw_stub() const { return true; }223virtual void visit(LIR_OpVisitState* visitor) {224visitor->do_slow_case(_info);225}226#ifndef PRODUCT227virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); }228#endif // PRODUCT229};230231232class NewInstanceStub: public CodeStub {233private:234ciInstanceKlass* _klass;235LIR_Opr _klass_reg;236LIR_Opr _result;237CodeEmitInfo* _info;238Runtime1::StubID _stub_id;239240public:241NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id);242virtual void emit_code(LIR_Assembler* e);243virtual CodeEmitInfo* info() const { return _info; }244virtual void visit(LIR_OpVisitState* visitor) {245visitor->do_slow_case(_info);246visitor->do_input(_klass_reg);247visitor->do_output(_result);248}249#ifndef PRODUCT250virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); }251#endif // PRODUCT252};253254255class NewTypeArrayStub: public CodeStub {256private:257LIR_Opr _klass_reg;258LIR_Opr _length;259LIR_Opr _result;260CodeEmitInfo* _info;261262public:263NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);264virtual void emit_code(LIR_Assembler* e);265virtual CodeEmitInfo* info() const { return _info; }266virtual void visit(LIR_OpVisitState* visitor) {267visitor->do_slow_case(_info);268visitor->do_input(_klass_reg);269visitor->do_input(_length);270assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);271}272#ifndef PRODUCT273virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); }274#endif // PRODUCT275};276277278class NewObjectArrayStub: public CodeStub {279private:280LIR_Opr _klass_reg;281LIR_Opr _length;282LIR_Opr _result;283CodeEmitInfo* _info;284285public:286NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info);287virtual void emit_code(LIR_Assembler* e);288virtual CodeEmitInfo* info() const { return _info; }289virtual void visit(LIR_OpVisitState* visitor) {290visitor->do_slow_case(_info);291visitor->do_input(_klass_reg);292visitor->do_input(_length);293assert(_result->is_valid(), "must be valid"); visitor->do_output(_result);294}295#ifndef PRODUCT296virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); }297#endif // PRODUCT298};299300301class MonitorAccessStub: public CodeStub {302protected:303LIR_Opr _obj_reg;304LIR_Opr _lock_reg;305306public:307MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) {308_obj_reg = obj_reg;309_lock_reg = lock_reg;310}311312#ifndef PRODUCT313virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); }314#endif // PRODUCT315};316317318class MonitorEnterStub: public MonitorAccessStub {319private:320CodeEmitInfo* _info;321322public:323MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info);324325virtual void emit_code(LIR_Assembler* e);326virtual CodeEmitInfo* info() const { return _info; }327virtual void visit(LIR_OpVisitState* visitor) {328visitor->do_input(_obj_reg);329visitor->do_input(_lock_reg);330visitor->do_slow_case(_info);331}332#ifndef PRODUCT333virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); }334#endif // PRODUCT335};336337338class MonitorExitStub: public MonitorAccessStub {339private:340bool _compute_lock;341int _monitor_ix;342343public:344MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix)345: MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg),346_compute_lock(compute_lock), _monitor_ix(monitor_ix) { }347virtual void emit_code(LIR_Assembler* e);348virtual void visit(LIR_OpVisitState* visitor) {349assert(_obj_reg->is_illegal(), "unused");350if (_compute_lock) {351visitor->do_temp(_lock_reg);352} else {353visitor->do_input(_lock_reg);354}355}356#ifndef PRODUCT357virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); }358#endif // PRODUCT359};360361362class PatchingStub: public CodeStub {363public:364enum PatchID {365access_field_id,366load_klass_id,367load_mirror_id,368load_appendix_id369};370enum constants {371patch_info_size = 3372};373private:374PatchID _id;375address _pc_start;376int _bytes_to_copy;377Label _patched_code_entry;378Label _patch_site_entry;379Label _patch_site_continuation;380Register _obj;381CodeEmitInfo* _info;382int _index; // index of the patchable oop or Klass* in nmethod oop or metadata table if needed383static int _patch_info_offset;384385void align_patch_site(MacroAssembler* masm);386387public:388static int patch_info_offset() { return _patch_info_offset; }389390PatchingStub(MacroAssembler* masm, PatchID id, int index = -1):391_id(id)392, _info(NULL)393, _index(index) {394if (os::is_MP()) {395// force alignment of patch sites on MP hardware so we396// can guarantee atomic writes to the patch site.397align_patch_site(masm);398}399_pc_start = masm->pc();400masm->bind(_patch_site_entry);401}402403void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {404_info = info;405_obj = obj;406masm->bind(_patch_site_continuation);407_bytes_to_copy = masm->pc() - pc_start();408if (_id == PatchingStub::access_field_id) {409// embed a fixed offset to handle long patches which need to be offset by a word.410// the patching code will just add the field offset field to this offset so411// that we can refernce either the high or low word of a double word field.412int field_offset = 0;413switch (patch_code) {414case lir_patch_low: field_offset = lo_word_offset_in_bytes; break;415case lir_patch_high: field_offset = hi_word_offset_in_bytes; break;416case lir_patch_normal: field_offset = 0; break;417default: ShouldNotReachHere();418}419NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());420n_move->set_offset(field_offset);421} else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {422assert(_obj != noreg, "must have register object for load_klass/load_mirror");423#ifdef ASSERT424// verify that we're pointing at a NativeMovConstReg425nativeMovConstReg_at(pc_start());426#endif427} else {428ShouldNotReachHere();429}430assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes");431}432433address pc_start() const { return _pc_start; }434PatchID id() const { return _id; }435436virtual void emit_code(LIR_Assembler* e);437virtual CodeEmitInfo* info() const { return _info; }438virtual void visit(LIR_OpVisitState* visitor) {439visitor->do_slow_case(_info);440}441#ifndef PRODUCT442virtual void print_name(outputStream* out) const { out->print("PatchingStub"); }443#endif // PRODUCT444};445446447//------------------------------------------------------------------------------448// DeoptimizeStub449//450class DeoptimizeStub : public CodeStub {451private:452CodeEmitInfo* _info;453454public:455DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {}456457virtual void emit_code(LIR_Assembler* e);458virtual CodeEmitInfo* info() const { return _info; }459virtual bool is_exception_throw_stub() const { return true; }460virtual void visit(LIR_OpVisitState* visitor) {461visitor->do_slow_case(_info);462}463#ifndef PRODUCT464virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); }465#endif // PRODUCT466};467468469class SimpleExceptionStub: public CodeStub {470private:471LIR_Opr _obj;472Runtime1::StubID _stub;473CodeEmitInfo* _info;474475public:476SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info):477_obj(obj), _info(info), _stub(stub) {478}479480void set_obj(LIR_Opr obj) {481_obj = obj;482}483484virtual void emit_code(LIR_Assembler* e);485virtual CodeEmitInfo* info() const { return _info; }486virtual bool is_exception_throw_stub() const { return true; }487virtual bool is_simple_exception_stub() const { return true; }488virtual void visit(LIR_OpVisitState* visitor) {489if (_obj->is_valid()) visitor->do_input(_obj);490visitor->do_slow_case(_info);491}492#ifndef PRODUCT493virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); }494#endif // PRODUCT495};496497498499class ArrayStoreExceptionStub: public SimpleExceptionStub {500private:501CodeEmitInfo* _info;502503public:504ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {}505#ifndef PRODUCT506virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }507#endif // PRODUCT508};509510511class ArrayCopyStub: public CodeStub {512private:513LIR_OpArrayCopy* _op;514515public:516ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { }517518LIR_Opr src() const { return _op->src(); }519LIR_Opr src_pos() const { return _op->src_pos(); }520LIR_Opr dst() const { return _op->dst(); }521LIR_Opr dst_pos() const { return _op->dst_pos(); }522LIR_Opr length() const { return _op->length(); }523LIR_Opr tmp() const { return _op->tmp(); }524525virtual void emit_code(LIR_Assembler* e);526virtual CodeEmitInfo* info() const { return _op->info(); }527virtual void visit(LIR_OpVisitState* visitor) {528// don't pass in the code emit info since it's processed in the fast path529visitor->do_slow_case();530}531#ifndef PRODUCT532virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); }533#endif // PRODUCT534};535536//////////////////////////////////////////////////////////////////////////////////////////537#if INCLUDE_ALL_GCS538539// Code stubs for Garbage-First barriers.540class G1PreBarrierStub: public CodeStub {541private:542bool _do_load;543LIR_Opr _addr;544LIR_Opr _pre_val;545LIR_PatchCode _patch_code;546CodeEmitInfo* _info;547548public:549// Version that _does_ generate a load of the previous value from addr.550// addr (the address of the field to be read) must be a LIR_Address551// pre_val (a temporary register) must be a register;552G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) :553_addr(addr), _pre_val(pre_val), _do_load(true),554_patch_code(patch_code), _info(info)555{556assert(_pre_val->is_register(), "should be temporary register");557assert(_addr->is_address(), "should be the address of the field");558}559560// Version that _does not_ generate load of the previous value; the561// previous value is assumed to have already been loaded into pre_val.562G1PreBarrierStub(LIR_Opr pre_val) :563_addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false),564_patch_code(lir_patch_none), _info(NULL)565{566assert(_pre_val->is_register(), "should be a register");567}568569LIR_Opr addr() const { return _addr; }570LIR_Opr pre_val() const { return _pre_val; }571LIR_PatchCode patch_code() const { return _patch_code; }572CodeEmitInfo* info() const { return _info; }573bool do_load() const { return _do_load; }574575virtual void emit_code(LIR_Assembler* e);576virtual void visit(LIR_OpVisitState* visitor) {577if (_do_load) {578// don't pass in the code emit info since it's processed in the fast579// path580if (_info != NULL)581visitor->do_slow_case(_info);582else583visitor->do_slow_case();584585visitor->do_input(_addr);586visitor->do_temp(_pre_val);587} else {588visitor->do_slow_case();589visitor->do_input(_pre_val);590}591}592#ifndef PRODUCT593virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); }594#endif // PRODUCT595};596597class G1PostBarrierStub: public CodeStub {598private:599LIR_Opr _addr;600LIR_Opr _new_val;601602static jbyte* _byte_map_base;603static jbyte* byte_map_base_slow();604static jbyte* byte_map_base() {605if (_byte_map_base == NULL) {606_byte_map_base = byte_map_base_slow();607}608return _byte_map_base;609}610611public:612// addr (the address of the object head) and new_val must be registers.613G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }614615LIR_Opr addr() const { return _addr; }616LIR_Opr new_val() const { return _new_val; }617618virtual void emit_code(LIR_Assembler* e);619virtual void visit(LIR_OpVisitState* visitor) {620// don't pass in the code emit info since it's processed in the fast path621visitor->do_slow_case();622visitor->do_input(_addr);623visitor->do_input(_new_val);624}625#ifndef PRODUCT626virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); }627#endif // PRODUCT628};629630#endif // INCLUDE_ALL_GCS631//////////////////////////////////////////////////////////////////////////////////////////632633#endif // SHARE_VM_C1_C1_CODESTUBS_HPP634635636