Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/cpu/aarch64/vm/c1_CodeStubs_aarch64.cpp
32285 views
/*1* Copyright (c) 2013, Red Hat Inc.2* Copyright (c) 1999, 2011, Oracle and/or its affiliates.3* All rights reserved.4* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.5*6* This code is free software; you can redistribute it and/or modify it7* under the terms of the GNU General Public License version 2 only, as8* published by the Free Software Foundation.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*24*/2526#include "precompiled.hpp"27#include "c1/c1_CodeStubs.hpp"28#include "c1/c1_FrameMap.hpp"29#include "c1/c1_LIRAssembler.hpp"30#include "c1/c1_MacroAssembler.hpp"31#include "c1/c1_Runtime1.hpp"32#include "nativeInst_aarch64.hpp"33#include "runtime/sharedRuntime.hpp"34#include "vmreg_aarch64.inline.hpp"35#if INCLUDE_ALL_GCS36#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"37#endif383940#define __ ce->masm()->4142float ConversionStub::float_zero = 0.0;43double ConversionStub::double_zero = 0.0;4445static Register as_reg(LIR_Opr op) {46return op->is_double_cpu() ? op->as_register_lo() : op->as_register();47}4849void ConversionStub::emit_code(LIR_Assembler* ce) {50__ bind(_entry);5152// FIXME: Agh, this is so painful5354__ enter();55__ sub(sp, sp, 2 * wordSize);56__ push(RegSet::range(r0, r29), sp); // integer registers except lr & sp57for (int i = 30; i >= 0; i -= 2) // caller-saved fp registers58if (i < 8 || i > 15)59__ stpd(as_FloatRegister(i), as_FloatRegister(i+1),60Address(__ pre(sp, -2 * wordSize)));6162switch(bytecode()) {63case Bytecodes::_f2i:64{65if (v0 != input()->as_float_reg())66__ fmovs(v0, input()->as_float_reg());67__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i));68}69break;70case Bytecodes::_d2i:71{72if (v0 != input()->as_double_reg())73__ fmovd(v0, input()->as_double_reg());74__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i));75}76break;77case Bytecodes::_f2l:78{79if (v0 != input()->as_float_reg())80__ fmovs(v0, input()->as_float_reg());81__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l));82}83break;84case Bytecodes::_d2l:85{86if (v0 != input()->as_double_reg())87__ fmovd(v0, input()->as_double_reg());88__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l));89}90break;91default:92ShouldNotReachHere();93}9495__ str(r0, Address(rfp, -wordSize));9697for (int i = 0; i < 32; i += 2)98if (i < 8 || i > 15)99__ ldpd(as_FloatRegister(i), as_FloatRegister(i+1),100Address(__ post(sp, 2 * wordSize)));101__ pop(RegSet::range(r0, r29), sp);102103__ ldr(as_reg(result()), Address(rfp, -wordSize));104__ leave();105106__ b(_continuation);107}108109void CounterOverflowStub::emit_code(LIR_Assembler* ce) {110__ bind(_entry);111ce->store_parameter(_method->as_register(), 1);112ce->store_parameter(_bci, 0);113__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::counter_overflow_id)));114ce->add_call_info_here(_info);115ce->verify_oop_map(_info);116__ b(_continuation);117}118119RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index,120bool throw_index_out_of_bounds_exception)121: _throw_index_out_of_bounds_exception(throw_index_out_of_bounds_exception)122, _index(index)123{124assert(info != NULL, "must have info");125_info = new CodeEmitInfo(info);126}127128void RangeCheckStub::emit_code(LIR_Assembler* ce) {129__ bind(_entry);130if (_info->deoptimize_on_exception()) {131address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);132__ far_call(RuntimeAddress(a));133ce->add_call_info_here(_info);134ce->verify_oop_map(_info);135debug_only(__ should_not_reach_here());136return;137}138139if (_index->is_cpu_register()) {140__ mov(rscratch1, _index->as_register());141} else {142__ mov(rscratch1, _index->as_jint());143}144Runtime1::StubID stub_id;145if (_throw_index_out_of_bounds_exception) {146stub_id = Runtime1::throw_index_exception_id;147} else {148stub_id = Runtime1::throw_range_check_failed_id;149}150__ far_call(RuntimeAddress(Runtime1::entry_for(stub_id)), NULL, rscratch2);151ce->add_call_info_here(_info);152ce->verify_oop_map(_info);153debug_only(__ should_not_reach_here());154}155156PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {157_info = new CodeEmitInfo(info);158}159160void PredicateFailedStub::emit_code(LIR_Assembler* ce) {161__ bind(_entry);162address a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);163__ far_call(RuntimeAddress(a));164ce->add_call_info_here(_info);165ce->verify_oop_map(_info);166debug_only(__ should_not_reach_here());167}168169void DivByZeroStub::emit_code(LIR_Assembler* ce) {170if (_offset != -1) {171ce->compilation()->implicit_exception_table()->append(_offset, __ offset());172}173__ bind(_entry);174__ far_call(Address(Runtime1::entry_for(Runtime1::throw_div0_exception_id), relocInfo::runtime_call_type));175ce->add_call_info_here(_info);176ce->verify_oop_map(_info);177#ifdef ASSERT178__ should_not_reach_here();179#endif180}181182183184// Implementation of NewInstanceStub185186NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id) {187_result = result;188_klass = klass;189_klass_reg = klass_reg;190_info = new CodeEmitInfo(info);191assert(stub_id == Runtime1::new_instance_id ||192stub_id == Runtime1::fast_new_instance_id ||193stub_id == Runtime1::fast_new_instance_init_check_id,194"need new_instance id");195_stub_id = stub_id;196}197198199200void NewInstanceStub::emit_code(LIR_Assembler* ce) {201assert(__ rsp_offset() == 0, "frame size should be fixed");202__ bind(_entry);203__ mov(r3, _klass_reg->as_register());204__ far_call(RuntimeAddress(Runtime1::entry_for(_stub_id)));205ce->add_call_info_here(_info);206ce->verify_oop_map(_info);207assert(_result->as_register() == r0, "result must in r0,");208__ b(_continuation);209}210211212// Implementation of NewTypeArrayStub213214// Implementation of NewTypeArrayStub215216NewTypeArrayStub::NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) {217_klass_reg = klass_reg;218_length = length;219_result = result;220_info = new CodeEmitInfo(info);221}222223224void NewTypeArrayStub::emit_code(LIR_Assembler* ce) {225assert(__ rsp_offset() == 0, "frame size should be fixed");226__ bind(_entry);227assert(_length->as_register() == r19, "length must in r19,");228assert(_klass_reg->as_register() == r3, "klass_reg must in r3");229__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_type_array_id)));230ce->add_call_info_here(_info);231ce->verify_oop_map(_info);232assert(_result->as_register() == r0, "result must in r0");233__ b(_continuation);234}235236237// Implementation of NewObjectArrayStub238239NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) {240_klass_reg = klass_reg;241_result = result;242_length = length;243_info = new CodeEmitInfo(info);244}245246247void NewObjectArrayStub::emit_code(LIR_Assembler* ce) {248assert(__ rsp_offset() == 0, "frame size should be fixed");249__ bind(_entry);250assert(_length->as_register() == r19, "length must in r19,");251assert(_klass_reg->as_register() == r3, "klass_reg must in r3");252__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_object_array_id)));253ce->add_call_info_here(_info);254ce->verify_oop_map(_info);255assert(_result->as_register() == r0, "result must in r0");256__ b(_continuation);257}258// Implementation of MonitorAccessStubs259260MonitorEnterStub::MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info)261: MonitorAccessStub(obj_reg, lock_reg)262{263_info = new CodeEmitInfo(info);264}265266267void MonitorEnterStub::emit_code(LIR_Assembler* ce) {268assert(__ rsp_offset() == 0, "frame size should be fixed");269__ bind(_entry);270ce->store_parameter(_obj_reg->as_register(), 1);271ce->store_parameter(_lock_reg->as_register(), 0);272Runtime1::StubID enter_id;273if (ce->compilation()->has_fpu_code()) {274enter_id = Runtime1::monitorenter_id;275} else {276enter_id = Runtime1::monitorenter_nofpu_id;277}278__ far_call(RuntimeAddress(Runtime1::entry_for(enter_id)));279ce->add_call_info_here(_info);280ce->verify_oop_map(_info);281__ b(_continuation);282}283284285void MonitorExitStub::emit_code(LIR_Assembler* ce) {286__ bind(_entry);287if (_compute_lock) {288// lock_reg was destroyed by fast unlocking attempt => recompute it289ce->monitor_address(_monitor_ix, _lock_reg);290}291ce->store_parameter(_lock_reg->as_register(), 0);292// note: non-blocking leaf routine => no call info needed293Runtime1::StubID exit_id;294if (ce->compilation()->has_fpu_code()) {295exit_id = Runtime1::monitorexit_id;296} else {297exit_id = Runtime1::monitorexit_nofpu_id;298}299__ adr(lr, _continuation);300__ far_jump(RuntimeAddress(Runtime1::entry_for(exit_id)));301}302303304// Implementation of patching:305// - Copy the code at given offset to an inlined buffer (first the bytes, then the number of bytes)306// - Replace original code with a call to the stub307// At Runtime:308// - call to stub, jump to runtime309// - in runtime: preserve all registers (rspecially objects, i.e., source and destination object)310// - in runtime: after initializing class, restore original code, reexecute instruction311312int PatchingStub::_patch_info_offset = -NativeGeneralJump::instruction_size;313314void PatchingStub::align_patch_site(MacroAssembler* masm) {315}316317void PatchingStub::emit_code(LIR_Assembler* ce) {318assert(false, "AArch64 should not use C1 runtime patching");319}320321322void DeoptimizeStub::emit_code(LIR_Assembler* ce) {323__ bind(_entry);324__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::deoptimize_id)));325ce->add_call_info_here(_info);326DEBUG_ONLY(__ should_not_reach_here());327}328329330void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {331address a;332if (_info->deoptimize_on_exception()) {333// Deoptimize, do not throw the exception, because it is probably wrong to do it here.334a = Runtime1::entry_for(Runtime1::predicate_failed_trap_id);335} else {336a = Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id);337}338339ce->compilation()->implicit_exception_table()->append(_offset, __ offset());340__ bind(_entry);341__ far_call(RuntimeAddress(a));342ce->add_call_info_here(_info);343ce->verify_oop_map(_info);344debug_only(__ should_not_reach_here());345}346347348void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {349assert(__ rsp_offset() == 0, "frame size should be fixed");350351__ bind(_entry);352// pass the object in a scratch register because all other registers353// must be preserved354if (_obj->is_cpu_register()) {355__ mov(rscratch1, _obj->as_register());356}357__ far_call(RuntimeAddress(Runtime1::entry_for(_stub)), NULL, rscratch2);358ce->add_call_info_here(_info);359debug_only(__ should_not_reach_here());360}361362363void ArrayCopyStub::emit_code(LIR_Assembler* ce) {364//---------------slow case: call to native-----------------365__ bind(_entry);366// Figure out where the args should go367// This should really convert the IntrinsicID to the Method* and signature368// but I don't know how to do that.369//370VMRegPair args[5];371BasicType signature[5] = { T_OBJECT, T_INT, T_OBJECT, T_INT, T_INT};372SharedRuntime::java_calling_convention(signature, args, 5, true);373374// push parameters375// (src, src_pos, dest, destPos, length)376Register r[5];377r[0] = src()->as_register();378r[1] = src_pos()->as_register();379r[2] = dst()->as_register();380r[3] = dst_pos()->as_register();381r[4] = length()->as_register();382383// next registers will get stored on the stack384for (int i = 0; i < 5 ; i++ ) {385VMReg r_1 = args[i].first();386if (r_1->is_stack()) {387int st_off = r_1->reg2stack() * wordSize;388__ str (r[i], Address(sp, st_off));389} else {390assert(r[i] == args[i].first()->as_Register(), "Wrong register for arg ");391}392}393394ce->align_call(lir_static_call);395396ce->emit_static_call_stub();397if (ce->compilation()->bailed_out()) {398return; // CodeCache is full399}400Address resolve(SharedRuntime::get_resolve_static_call_stub(),401relocInfo::static_call_type);402address call = __ trampoline_call(resolve);403if (call == NULL) {404ce->bailout("trampoline stub overflow");405return;406}407ce->add_call_info_here(info());408409#ifndef PRODUCT410__ lea(rscratch2, ExternalAddress((address)&Runtime1::_arraycopy_slowcase_cnt));411__ incrementw(Address(rscratch2));412#endif413414__ b(_continuation);415}416417418/////////////////////////////////////////////////////////////////////////////419#if INCLUDE_ALL_GCS420421void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {422// At this point we know that marking is in progress.423// If do_load() is true then we have to emit the424// load of the previous value; otherwise it has already425// been loaded into _pre_val.426427__ bind(_entry);428assert(pre_val()->is_register(), "Precondition.");429430Register pre_val_reg = pre_val()->as_register();431432if (do_load()) {433ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);434}435__ cbz(pre_val_reg, _continuation);436ce->store_parameter(pre_val()->as_register(), 0);437__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id)));438__ b(_continuation);439}440441jbyte* G1PostBarrierStub::_byte_map_base = NULL;442443jbyte* G1PostBarrierStub::byte_map_base_slow() {444BarrierSet* bs = Universe::heap()->barrier_set();445assert(bs->is_a(BarrierSet::G1SATBCTLogging),446"Must be if we're using this.");447return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;448}449450451void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {452__ bind(_entry);453assert(addr()->is_register(), "Precondition.");454assert(new_val()->is_register(), "Precondition.");455Register new_val_reg = new_val()->as_register();456__ cbz(new_val_reg, _continuation);457ce->store_parameter(addr()->as_pointer_register(), 0);458__ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id)));459__ b(_continuation);460}461462#endif // INCLUDE_ALL_GCS463/////////////////////////////////////////////////////////////////////////////464465#undef __466467468