Path: blob/jdk8u272-b10-aarch32-20201026/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
48785 views
/*1* Copyright (c) 1999, 2018, 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#include "precompiled.hpp"25#include "asm/assembler.hpp"26#include "c1/c1_Defs.hpp"27#include "c1/c1_MacroAssembler.hpp"28#include "c1/c1_Runtime1.hpp"29#include "interpreter/interpreter.hpp"30#include "nativeInst_x86.hpp"31#include "oops/compiledICHolder.hpp"32#include "oops/oop.inline.hpp"33#include "prims/jvmtiExport.hpp"34#include "register_x86.hpp"35#include "runtime/sharedRuntime.hpp"36#include "runtime/signature.hpp"37#include "runtime/vframeArray.hpp"38#include "utilities/macros.hpp"39#include "vmreg_x86.inline.hpp"40#if INCLUDE_ALL_GCS41#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"42#endif434445// Implementation of StubAssembler4647int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) {48// setup registers49const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions)50assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different");51assert(oop_result1 != thread && metadata_result != thread, "registers must be different");52assert(args_size >= 0, "illegal args_size");53bool align_stack = false;54#ifdef _LP6455// At a method handle call, the stack may not be properly aligned56// when returning with an exception.57align_stack = (stub_id() == Runtime1::handle_exception_from_callee_id);58#endif5960#ifdef _LP6461mov(c_rarg0, thread);62set_num_rt_args(0); // Nothing on stack63#else64set_num_rt_args(1 + args_size);6566// push java thread (becomes first argument of C function)67get_thread(thread);68push(thread);69#endif // _LP647071int call_offset;72if (!align_stack) {73set_last_Java_frame(thread, noreg, rbp, NULL);74} else {75address the_pc = pc();76call_offset = offset();77set_last_Java_frame(thread, noreg, rbp, the_pc);78andptr(rsp, -(StackAlignmentInBytes)); // Align stack79}8081// do the call82call(RuntimeAddress(entry));83if (!align_stack) {84call_offset = offset();85}86// verify callee-saved register87#ifdef ASSERT88guarantee(thread != rax, "change this code");89push(rax);90{ Label L;91get_thread(rax);92cmpptr(thread, rax);93jcc(Assembler::equal, L);94int3();95stop("StubAssembler::call_RT: rdi not callee saved?");96bind(L);97}98pop(rax);99#endif100reset_last_Java_frame(thread, true);101102// discard thread and arguments103NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));104105// check for pending exceptions106{ Label L;107cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);108jcc(Assembler::equal, L);109// exception pending => remove activation and forward to exception handler110movptr(rax, Address(thread, Thread::pending_exception_offset()));111// make sure that the vm_results are cleared112if (oop_result1->is_valid()) {113movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD);114}115if (metadata_result->is_valid()) {116movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD);117}118if (frame_size() == no_frame_size) {119leave();120jump(RuntimeAddress(StubRoutines::forward_exception_entry()));121} else if (_stub_id == Runtime1::forward_exception_id) {122should_not_reach_here();123} else {124jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id)));125}126bind(L);127}128// get oop results if there are any and reset the values in the thread129if (oop_result1->is_valid()) {130get_vm_result(oop_result1, thread);131}132if (metadata_result->is_valid()) {133get_vm_result_2(metadata_result, thread);134}135return call_offset;136}137138139int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1) {140#ifdef _LP64141mov(c_rarg1, arg1);142#else143push(arg1);144#endif // _LP64145return call_RT(oop_result1, metadata_result, entry, 1);146}147148149int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2) {150#ifdef _LP64151if (c_rarg1 == arg2) {152if (c_rarg2 == arg1) {153xchgq(arg1, arg2);154} else {155mov(c_rarg2, arg2);156mov(c_rarg1, arg1);157}158} else {159mov(c_rarg1, arg1);160mov(c_rarg2, arg2);161}162#else163push(arg2);164push(arg1);165#endif // _LP64166return call_RT(oop_result1, metadata_result, entry, 2);167}168169170int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3) {171#ifdef _LP64172// if there is any conflict use the stack173if (arg1 == c_rarg2 || arg1 == c_rarg3 ||174arg2 == c_rarg1 || arg1 == c_rarg3 ||175arg3 == c_rarg1 || arg1 == c_rarg2) {176push(arg3);177push(arg2);178push(arg1);179pop(c_rarg1);180pop(c_rarg2);181pop(c_rarg3);182} else {183mov(c_rarg1, arg1);184mov(c_rarg2, arg2);185mov(c_rarg3, arg3);186}187#else188push(arg3);189push(arg2);190push(arg1);191#endif // _LP64192return call_RT(oop_result1, metadata_result, entry, 3);193}194195196// Implementation of StubFrame197198class StubFrame: public StackObj {199private:200StubAssembler* _sasm;201202public:203StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments);204void load_argument(int offset_in_words, Register reg);205206~StubFrame();207};208209210#define __ _sasm->211212StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) {213_sasm = sasm;214__ set_info(name, must_gc_arguments);215__ enter();216}217218// load parameters that were stored with LIR_Assembler::store_parameter219// Note: offsets for store_parameter and load_argument must match220void StubFrame::load_argument(int offset_in_words, Register reg) {221// rbp, + 0: link222// + 1: return address223// + 2: argument with offset 0224// + 3: argument with offset 1225// + 4: ...226227__ movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord));228}229230231StubFrame::~StubFrame() {232__ leave();233__ ret(0);234}235236#undef __237238239// Implementation of Runtime1240241#define __ sasm->242243const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;244const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2;245246// Stack layout for saving/restoring all the registers needed during a runtime247// call (this includes deoptimization)248// Note: note that users of this frame may well have arguments to some runtime249// while these values are on the stack. These positions neglect those arguments250// but the code in save_live_registers will take the argument count into251// account.252//253#ifdef _LP64254#define SLOT2(x) x,255#define SLOT_PER_WORD 2256#else257#define SLOT2(x)258#define SLOT_PER_WORD 1259#endif // _LP64260261enum reg_save_layout {262// 64bit needs to keep stack 16 byte aligned. So we add some alignment dummies to make that263// happen and will assert if the stack size we create is misaligned264#ifdef _LP64265align_dummy_0, align_dummy_1,266#endif // _LP64267#ifdef _WIN64268// Windows always allocates space for it's argument registers (see269// frame::arg_reg_save_area_bytes).270arg_reg_save_1, arg_reg_save_1H, // 0, 4271arg_reg_save_2, arg_reg_save_2H, // 8, 12272arg_reg_save_3, arg_reg_save_3H, // 16, 20273arg_reg_save_4, arg_reg_save_4H, // 24, 28274#endif // _WIN64275xmm_regs_as_doubles_off, // 32276float_regs_as_doubles_off = xmm_regs_as_doubles_off + xmm_regs_as_doubles_size_in_slots, // 160277fpu_state_off = float_regs_as_doubles_off + float_regs_as_doubles_size_in_slots, // 224278// fpu_state_end_off is exclusive279fpu_state_end_off = fpu_state_off + (FPUStateSizeInWords / SLOT_PER_WORD), // 352280marker = fpu_state_end_off, SLOT2(markerH) // 352, 356281extra_space_offset, // 360282#ifdef _LP64283r15_off = extra_space_offset, r15H_off, // 360, 364284r14_off, r14H_off, // 368, 372285r13_off, r13H_off, // 376, 380286r12_off, r12H_off, // 384, 388287r11_off, r11H_off, // 392, 396288r10_off, r10H_off, // 400, 404289r9_off, r9H_off, // 408, 412290r8_off, r8H_off, // 416, 420291rdi_off, rdiH_off, // 424, 428292#else293rdi_off = extra_space_offset,294#endif // _LP64295rsi_off, SLOT2(rsiH_off) // 432, 436296rbp_off, SLOT2(rbpH_off) // 440, 444297rsp_off, SLOT2(rspH_off) // 448, 452298rbx_off, SLOT2(rbxH_off) // 456, 460299rdx_off, SLOT2(rdxH_off) // 464, 468300rcx_off, SLOT2(rcxH_off) // 472, 476301rax_off, SLOT2(raxH_off) // 480, 484302saved_rbp_off, SLOT2(saved_rbpH_off) // 488, 492303return_off, SLOT2(returnH_off) // 496, 500304reg_save_frame_size // As noted: neglects any parameters to runtime // 504305};306307308309// Save off registers which might be killed by calls into the runtime.310// Tries to smart of about FP registers. In particular we separate311// saving and describing the FPU registers for deoptimization since we312// have to save the FPU registers twice if we describe them and on P4313// saving FPU registers which don't contain anything appears314// expensive. The deopt blob is the only thing which needs to315// describe FPU registers. In all other cases it should be sufficient316// to simply save their current value.317318static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,319bool save_fpu_registers = true) {320321// In 64bit all the args are in regs so there are no additional stack slots322LP64_ONLY(num_rt_args = 0);323LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");)324int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread325sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word );326327// record saved value locations in an OopMap328// locations are offsets from sp after runtime call; num_rt_args is number of arguments in call, including thread329OopMap* map = new OopMap(frame_size_in_slots, 0);330map->set_callee_saved(VMRegImpl::stack2reg(rax_off + num_rt_args), rax->as_VMReg());331map->set_callee_saved(VMRegImpl::stack2reg(rcx_off + num_rt_args), rcx->as_VMReg());332map->set_callee_saved(VMRegImpl::stack2reg(rdx_off + num_rt_args), rdx->as_VMReg());333map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg());334map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg());335map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg());336#ifdef _LP64337map->set_callee_saved(VMRegImpl::stack2reg(r8_off + num_rt_args), r8->as_VMReg());338map->set_callee_saved(VMRegImpl::stack2reg(r9_off + num_rt_args), r9->as_VMReg());339map->set_callee_saved(VMRegImpl::stack2reg(r10_off + num_rt_args), r10->as_VMReg());340map->set_callee_saved(VMRegImpl::stack2reg(r11_off + num_rt_args), r11->as_VMReg());341map->set_callee_saved(VMRegImpl::stack2reg(r12_off + num_rt_args), r12->as_VMReg());342map->set_callee_saved(VMRegImpl::stack2reg(r13_off + num_rt_args), r13->as_VMReg());343map->set_callee_saved(VMRegImpl::stack2reg(r14_off + num_rt_args), r14->as_VMReg());344map->set_callee_saved(VMRegImpl::stack2reg(r15_off + num_rt_args), r15->as_VMReg());345346// This is stupid but needed.347map->set_callee_saved(VMRegImpl::stack2reg(raxH_off + num_rt_args), rax->as_VMReg()->next());348map->set_callee_saved(VMRegImpl::stack2reg(rcxH_off + num_rt_args), rcx->as_VMReg()->next());349map->set_callee_saved(VMRegImpl::stack2reg(rdxH_off + num_rt_args), rdx->as_VMReg()->next());350map->set_callee_saved(VMRegImpl::stack2reg(rbxH_off + num_rt_args), rbx->as_VMReg()->next());351map->set_callee_saved(VMRegImpl::stack2reg(rsiH_off + num_rt_args), rsi->as_VMReg()->next());352map->set_callee_saved(VMRegImpl::stack2reg(rdiH_off + num_rt_args), rdi->as_VMReg()->next());353354map->set_callee_saved(VMRegImpl::stack2reg(r8H_off + num_rt_args), r8->as_VMReg()->next());355map->set_callee_saved(VMRegImpl::stack2reg(r9H_off + num_rt_args), r9->as_VMReg()->next());356map->set_callee_saved(VMRegImpl::stack2reg(r10H_off + num_rt_args), r10->as_VMReg()->next());357map->set_callee_saved(VMRegImpl::stack2reg(r11H_off + num_rt_args), r11->as_VMReg()->next());358map->set_callee_saved(VMRegImpl::stack2reg(r12H_off + num_rt_args), r12->as_VMReg()->next());359map->set_callee_saved(VMRegImpl::stack2reg(r13H_off + num_rt_args), r13->as_VMReg()->next());360map->set_callee_saved(VMRegImpl::stack2reg(r14H_off + num_rt_args), r14->as_VMReg()->next());361map->set_callee_saved(VMRegImpl::stack2reg(r15H_off + num_rt_args), r15->as_VMReg()->next());362#endif // _LP64363364if (save_fpu_registers) {365if (UseSSE < 2) {366int fpu_off = float_regs_as_doubles_off;367for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {368VMReg fpu_name_0 = FrameMap::fpu_regname(n);369map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + num_rt_args), fpu_name_0);370// %%% This is really a waste but we'll keep things as they were for now371if (true) {372map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + 1 + num_rt_args), fpu_name_0->next());373}374fpu_off += 2;375}376assert(fpu_off == fpu_state_off, "incorrect number of fpu stack slots");377}378379if (UseSSE >= 2) {380int xmm_off = xmm_regs_as_doubles_off;381for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {382VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();383map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);384// %%% This is really a waste but we'll keep things as they were for now385if (true) {386map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + 1 + num_rt_args), xmm_name_0->next());387}388xmm_off += 2;389}390assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");391392} else if (UseSSE == 1) {393int xmm_off = xmm_regs_as_doubles_off;394for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {395VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();396map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);397xmm_off += 2;398}399assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");400}401}402403return map;404}405406static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,407bool save_fpu_registers = true) {408__ block_comment("save_live_registers");409410__ pusha(); // integer registers411412// assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset");413// assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset");414415__ subptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);416417#ifdef ASSERT418__ movptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef);419#endif420421if (save_fpu_registers) {422if (UseSSE < 2) {423// save FPU stack424__ fnsave(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));425__ fwait();426427#ifdef ASSERT428Label ok;429__ cmpw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::fpu_cntrl_wrd_std());430__ jccb(Assembler::equal, ok);431__ stop("corrupted control word detected");432__ bind(ok);433#endif434435// Reset the control word to guard against exceptions being unmasked436// since fstp_d can cause FPU stack underflow exceptions. Write it437// into the on stack copy and then reload that to make sure that the438// current and future values are correct.439__ movw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::fpu_cntrl_wrd_std());440__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));441442// Save the FPU registers in de-opt-able form443__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));444__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));445__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));446__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));447__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));448__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));449__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));450__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));451}452453if (UseSSE >= 2) {454// save XMM registers455// XMM registers can contain float or double values, but this is not known here,456// so always save them as doubles.457// note that float values are _not_ converted automatically, so for float values458// the second word contains only garbage data.459__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);460__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);461__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);462__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);463__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);464__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);465__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);466__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);467#ifdef _LP64468__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64), xmm8);469__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72), xmm9);470__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80), xmm10);471__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88), xmm11);472__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96), xmm12);473__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13);474__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112), xmm14);475__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15);476#endif // _LP64477} else if (UseSSE == 1) {478// save XMM registers as float because double not supported without SSE2479__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);480__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);481__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);482__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);483__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);484__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);485__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);486__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);487}488}489490// FPU stack must be empty now491__ verify_FPU(0, "save_live_registers");492493return generate_oop_map(sasm, num_rt_args, save_fpu_registers);494}495496497static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true) {498if (restore_fpu_registers) {499if (UseSSE >= 2) {500// restore XMM registers501__ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));502__ movdbl(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));503__ movdbl(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));504__ movdbl(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));505__ movdbl(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));506__ movdbl(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));507__ movdbl(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));508__ movdbl(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));509#ifdef _LP64510__ movdbl(xmm8, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64));511__ movdbl(xmm9, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72));512__ movdbl(xmm10, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80));513__ movdbl(xmm11, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88));514__ movdbl(xmm12, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96));515__ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104));516__ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112));517__ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120));518#endif // _LP64519} else if (UseSSE == 1) {520// restore XMM registers521__ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));522__ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));523__ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));524__ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));525__ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));526__ movflt(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));527__ movflt(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));528__ movflt(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));529}530531if (UseSSE < 2) {532__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));533} else {534// check that FPU stack is really empty535__ verify_FPU(0, "restore_live_registers");536}537538} else {539// check that FPU stack is really empty540__ verify_FPU(0, "restore_live_registers");541}542543#ifdef ASSERT544{545Label ok;546__ cmpptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef);547__ jcc(Assembler::equal, ok);548__ stop("bad offsets in frame");549__ bind(ok);550}551#endif // ASSERT552553__ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);554}555556557static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {558__ block_comment("restore_live_registers");559560restore_fpu(sasm, restore_fpu_registers);561__ popa();562}563564565static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) {566__ block_comment("restore_live_registers_except_rax");567568restore_fpu(sasm, restore_fpu_registers);569570#ifdef _LP64571__ movptr(r15, Address(rsp, 0));572__ movptr(r14, Address(rsp, wordSize));573__ movptr(r13, Address(rsp, 2 * wordSize));574__ movptr(r12, Address(rsp, 3 * wordSize));575__ movptr(r11, Address(rsp, 4 * wordSize));576__ movptr(r10, Address(rsp, 5 * wordSize));577__ movptr(r9, Address(rsp, 6 * wordSize));578__ movptr(r8, Address(rsp, 7 * wordSize));579__ movptr(rdi, Address(rsp, 8 * wordSize));580__ movptr(rsi, Address(rsp, 9 * wordSize));581__ movptr(rbp, Address(rsp, 10 * wordSize));582// skip rsp583__ movptr(rbx, Address(rsp, 12 * wordSize));584__ movptr(rdx, Address(rsp, 13 * wordSize));585__ movptr(rcx, Address(rsp, 14 * wordSize));586587__ addptr(rsp, 16 * wordSize);588#else589590__ pop(rdi);591__ pop(rsi);592__ pop(rbp);593__ pop(rbx); // skip this value594__ pop(rbx);595__ pop(rdx);596__ pop(rcx);597__ addptr(rsp, BytesPerWord);598#endif // _LP64599}600601602void Runtime1::initialize_pd() {603// nothing to do604}605606607// target: the entry point of the method that creates and posts the exception oop608// has_argument: true if the exception needs an argument (passed on stack because registers must be preserved)609610OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {611// preserve all registers612int num_rt_args = has_argument ? 2 : 1;613OopMap* oop_map = save_live_registers(sasm, num_rt_args);614615// now all registers are saved and can be used freely616// verify that no old value is used accidentally617__ invalidate_registers(true, true, true, true, true, true);618619// registers used by this stub620const Register temp_reg = rbx;621622// load argument for exception that is passed as an argument into the stub623if (has_argument) {624#ifdef _LP64625__ movptr(c_rarg1, Address(rbp, 2*BytesPerWord));626#else627__ movptr(temp_reg, Address(rbp, 2*BytesPerWord));628__ push(temp_reg);629#endif // _LP64630}631int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1);632633OopMapSet* oop_maps = new OopMapSet();634oop_maps->add_gc_map(call_offset, oop_map);635636__ stop("should not reach here");637638return oop_maps;639}640641642OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) {643__ block_comment("generate_handle_exception");644645// incoming parameters646const Register exception_oop = rax;647const Register exception_pc = rdx;648// other registers used in this stub649const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread);650651// Save registers, if required.652OopMapSet* oop_maps = new OopMapSet();653OopMap* oop_map = NULL;654switch (id) {655case forward_exception_id:656// We're handling an exception in the context of a compiled frame.657// The registers have been saved in the standard places. Perform658// an exception lookup in the caller and dispatch to the handler659// if found. Otherwise unwind and dispatch to the callers660// exception handler.661oop_map = generate_oop_map(sasm, 1 /*thread*/);662663// load and clear pending exception oop into RAX664__ movptr(exception_oop, Address(thread, Thread::pending_exception_offset()));665__ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);666667// load issuing PC (the return address for this stub) into rdx668__ movptr(exception_pc, Address(rbp, 1*BytesPerWord));669670// make sure that the vm_results are cleared (may be unnecessary)671__ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD);672__ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD);673break;674case handle_exception_nofpu_id:675case handle_exception_id:676// At this point all registers MAY be live.677oop_map = save_live_registers(sasm, 1 /*thread*/, id != handle_exception_nofpu_id);678break;679case handle_exception_from_callee_id: {680// At this point all registers except exception oop (RAX) and681// exception pc (RDX) are dead.682const int frame_size = 2 /*BP, return address*/ NOT_LP64(+ 1 /*thread*/) WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord);683oop_map = new OopMap(frame_size * VMRegImpl::slots_per_word, 0);684sasm->set_frame_size(frame_size);685WIN64_ONLY(__ subq(rsp, frame::arg_reg_save_area_bytes));686break;687}688default: ShouldNotReachHere();689}690691#ifdef TIERED692// C2 can leave the fpu stack dirty693if (UseSSE < 2) {694__ empty_FPU_stack();695}696#endif // TIERED697698// verify that only rax, and rdx is valid at this time699__ invalidate_registers(false, true, true, false, true, true);700// verify that rax, contains a valid exception701__ verify_not_null_oop(exception_oop);702703// load address of JavaThread object for thread-local data704NOT_LP64(__ get_thread(thread);)705706#ifdef ASSERT707// check that fields in JavaThread for exception oop and issuing pc are708// empty before writing to them709Label oop_empty;710__ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t) NULL_WORD);711__ jcc(Assembler::equal, oop_empty);712__ stop("exception oop already set");713__ bind(oop_empty);714715Label pc_empty;716__ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0);717__ jcc(Assembler::equal, pc_empty);718__ stop("exception pc already set");719__ bind(pc_empty);720#endif721722// save exception oop and issuing pc into JavaThread723// (exception handler will load it from here)724__ movptr(Address(thread, JavaThread::exception_oop_offset()), exception_oop);725__ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc);726727// patch throwing pc into return address (has bci & oop map)728__ movptr(Address(rbp, 1*BytesPerWord), exception_pc);729730// compute the exception handler.731// the exception oop and the throwing pc are read from the fields in JavaThread732int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc));733oop_maps->add_gc_map(call_offset, oop_map);734735// rax: handler address736// will be the deopt blob if nmethod was deoptimized while we looked up737// handler regardless of whether handler existed in the nmethod.738739// only rax, is valid at this time, all other registers have been destroyed by the runtime call740__ invalidate_registers(false, true, true, true, true, true);741742// patch the return address, this stub will directly return to the exception handler743__ movptr(Address(rbp, 1*BytesPerWord), rax);744745switch (id) {746case forward_exception_id:747case handle_exception_nofpu_id:748case handle_exception_id:749// Restore the registers that were saved at the beginning.750restore_live_registers(sasm, id != handle_exception_nofpu_id);751break;752case handle_exception_from_callee_id:753// WIN64_ONLY: No need to add frame::arg_reg_save_area_bytes to SP754// since we do a leave anyway.755756// Pop the return address.757__ leave();758__ pop(rcx);759__ jmp(rcx); // jump to exception handler760break;761default: ShouldNotReachHere();762}763764return oop_maps;765}766767768void Runtime1::generate_unwind_exception(StubAssembler *sasm) {769// incoming parameters770const Register exception_oop = rax;771// callee-saved copy of exception_oop during runtime call772const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14);773// other registers used in this stub774const Register exception_pc = rdx;775const Register handler_addr = rbx;776const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread);777778// verify that only rax, is valid at this time779__ invalidate_registers(false, true, true, true, true, true);780781#ifdef ASSERT782// check that fields in JavaThread for exception oop and issuing pc are empty783NOT_LP64(__ get_thread(thread);)784Label oop_empty;785__ cmpptr(Address(thread, JavaThread::exception_oop_offset()), 0);786__ jcc(Assembler::equal, oop_empty);787__ stop("exception oop must be empty");788__ bind(oop_empty);789790Label pc_empty;791__ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0);792__ jcc(Assembler::equal, pc_empty);793__ stop("exception pc must be empty");794__ bind(pc_empty);795#endif796797// clear the FPU stack in case any FPU results are left behind798__ empty_FPU_stack();799800// save exception_oop in callee-saved register to preserve it during runtime calls801__ verify_not_null_oop(exception_oop);802__ movptr(exception_oop_callee_saved, exception_oop);803804NOT_LP64(__ get_thread(thread);)805// Get return address (is on top of stack after leave).806__ movptr(exception_pc, Address(rsp, 0));807808// search the exception handler address of the caller (using the return address)809__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc);810// rax: exception handler address of the caller811812// Only RAX and RSI are valid at this time, all other registers have been destroyed by the call.813__ invalidate_registers(false, true, true, true, false, true);814815// move result of call into correct register816__ movptr(handler_addr, rax);817818// Restore exception oop to RAX (required convention of exception handler).819__ movptr(exception_oop, exception_oop_callee_saved);820821// verify that there is really a valid exception in rax822__ verify_not_null_oop(exception_oop);823824// get throwing pc (= return address).825// rdx has been destroyed by the call, so it must be set again826// the pop is also necessary to simulate the effect of a ret(0)827__ pop(exception_pc);828829// continue at exception handler (return address removed)830// note: do *not* remove arguments when unwinding the831// activation since the caller assumes having832// all arguments on the stack when entering the833// runtime to determine the exception handler834// (GC happens at call site with arguments!)835// rax: exception oop836// rdx: throwing pc837// rbx: exception handler838__ jmp(handler_addr);839}840841842OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) {843// use the maximum number of runtime-arguments here because it is difficult to844// distinguish each RT-Call.845// Note: This number affects also the RT-Call in generate_handle_exception because846// the oop-map is shared for all calls.847const int num_rt_args = 2; // thread + dummy848849DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();850assert(deopt_blob != NULL, "deoptimization blob must have been created");851852OopMap* oop_map = save_live_registers(sasm, num_rt_args);853854#ifdef _LP64855const Register thread = r15_thread;856// No need to worry about dummy857__ mov(c_rarg0, thread);858#else859__ push(rax); // push dummy860861const Register thread = rdi; // is callee-saved register (Visual C++ calling conventions)862// push java thread (becomes first argument of C function)863__ get_thread(thread);864__ push(thread);865#endif // _LP64866__ set_last_Java_frame(thread, noreg, rbp, NULL);867// do the call868__ call(RuntimeAddress(target));869OopMapSet* oop_maps = new OopMapSet();870oop_maps->add_gc_map(__ offset(), oop_map);871// verify callee-saved register872#ifdef ASSERT873guarantee(thread != rax, "change this code");874__ push(rax);875{ Label L;876__ get_thread(rax);877__ cmpptr(thread, rax);878__ jcc(Assembler::equal, L);879__ stop("StubAssembler::call_RT: rdi/r15 not callee saved?");880__ bind(L);881}882__ pop(rax);883#endif884__ reset_last_Java_frame(thread, true);885#ifndef _LP64886__ pop(rcx); // discard thread arg887__ pop(rcx); // discard dummy888#endif // _LP64889890// check for pending exceptions891{ Label L;892__ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);893__ jcc(Assembler::equal, L);894// exception pending => remove activation and forward to exception handler895896__ testptr(rax, rax); // have we deoptimized?897__ jump_cc(Assembler::equal,898RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id)));899900// the deopt blob expects exceptions in the special fields of901// JavaThread, so copy and clear pending exception.902903// load and clear pending exception904__ movptr(rax, Address(thread, Thread::pending_exception_offset()));905__ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);906907// check that there is really a valid exception908__ verify_not_null_oop(rax);909910// load throwing pc: this is the return address of the stub911__ movptr(rdx, Address(rsp, return_off * VMRegImpl::stack_slot_size));912913#ifdef ASSERT914// check that fields in JavaThread for exception oop and issuing pc are empty915Label oop_empty;916__ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD);917__ jcc(Assembler::equal, oop_empty);918__ stop("exception oop must be empty");919__ bind(oop_empty);920921Label pc_empty;922__ cmpptr(Address(thread, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD);923__ jcc(Assembler::equal, pc_empty);924__ stop("exception pc must be empty");925__ bind(pc_empty);926#endif927928// store exception oop and throwing pc to JavaThread929__ movptr(Address(thread, JavaThread::exception_oop_offset()), rax);930__ movptr(Address(thread, JavaThread::exception_pc_offset()), rdx);931932restore_live_registers(sasm);933934__ leave();935__ addptr(rsp, BytesPerWord); // remove return address from stack936937// Forward the exception directly to deopt blob. We can blow no938// registers and must leave throwing pc on the stack. A patch may939// have values live in registers so the entry point with the940// exception in tls.941__ jump(RuntimeAddress(deopt_blob->unpack_with_exception_in_tls()));942943__ bind(L);944}945946947// Runtime will return true if the nmethod has been deoptimized during948// the patching process. In that case we must do a deopt reexecute instead.949950Label reexecuteEntry, cont;951952__ testptr(rax, rax); // have we deoptimized?953__ jcc(Assembler::equal, cont); // no954955// Will reexecute. Proper return address is already on the stack we just restore956// registers, pop all of our frame but the return address and jump to the deopt blob957restore_live_registers(sasm);958__ leave();959__ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution()));960961__ bind(cont);962restore_live_registers(sasm);963__ leave();964__ ret(0);965966return oop_maps;967}968969970OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {971972// for better readability973const bool must_gc_arguments = true;974const bool dont_gc_arguments = false;975976// default value; overwritten for some optimized stubs that are called from methods that do not use the fpu977bool save_fpu_registers = true;978979// stub code & info for the different stubs980OopMapSet* oop_maps = NULL;981switch (id) {982case forward_exception_id:983{984oop_maps = generate_handle_exception(id, sasm);985__ leave();986__ ret(0);987}988break;989990case new_instance_id:991case fast_new_instance_id:992case fast_new_instance_init_check_id:993{994Register klass = rdx; // Incoming995Register obj = rax; // Result996997if (id == new_instance_id) {998__ set_info("new_instance", dont_gc_arguments);999} else if (id == fast_new_instance_id) {1000__ set_info("fast new_instance", dont_gc_arguments);1001} else {1002assert(id == fast_new_instance_init_check_id, "bad StubID");1003__ set_info("fast new_instance init check", dont_gc_arguments);1004}10051006if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) &&1007UseTLAB && FastTLABRefill) {1008Label slow_path;1009Register obj_size = rcx;1010Register t1 = rbx;1011Register t2 = rsi;1012assert_different_registers(klass, obj, obj_size, t1, t2);10131014__ push(rdi);1015__ push(rbx);10161017if (id == fast_new_instance_init_check_id) {1018// make sure the klass is initialized1019__ cmpb(Address(klass, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);1020__ jcc(Assembler::notEqual, slow_path);1021}10221023#ifdef ASSERT1024// assert object can be fast path allocated1025{1026Label ok, not_ok;1027__ movl(obj_size, Address(klass, Klass::layout_helper_offset()));1028__ cmpl(obj_size, 0); // make sure it's an instance (LH > 0)1029__ jcc(Assembler::lessEqual, not_ok);1030__ testl(obj_size, Klass::_lh_instance_slow_path_bit);1031__ jcc(Assembler::zero, ok);1032__ bind(not_ok);1033__ stop("assert(can be fast path allocated)");1034__ should_not_reach_here();1035__ bind(ok);1036}1037#endif // ASSERT10381039// if we got here then the TLAB allocation failed, so try1040// refilling the TLAB or allocating directly from eden.1041Label retry_tlab, try_eden;1042const Register thread =1043__ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass), returns rdi10441045__ bind(retry_tlab);10461047// get the instance size (size is postive so movl is fine for 64bit)1048__ movl(obj_size, Address(klass, Klass::layout_helper_offset()));10491050__ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path);10511052__ initialize_object(obj, klass, obj_size, 0, t1, t2);1053__ verify_oop(obj);1054__ pop(rbx);1055__ pop(rdi);1056__ ret(0);10571058__ bind(try_eden);1059// get the instance size (size is postive so movl is fine for 64bit)1060__ movl(obj_size, Address(klass, Klass::layout_helper_offset()));10611062__ eden_allocate(obj, obj_size, 0, t1, slow_path);1063__ incr_allocated_bytes(thread, obj_size, 0);10641065__ initialize_object(obj, klass, obj_size, 0, t1, t2);1066__ verify_oop(obj);1067__ pop(rbx);1068__ pop(rdi);1069__ ret(0);10701071__ bind(slow_path);1072__ pop(rbx);1073__ pop(rdi);1074}10751076__ enter();1077OopMap* map = save_live_registers(sasm, 2);1078int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass);1079oop_maps = new OopMapSet();1080oop_maps->add_gc_map(call_offset, map);1081restore_live_registers_except_rax(sasm);1082__ verify_oop(obj);1083__ leave();1084__ ret(0);10851086// rax,: new instance1087}10881089break;10901091case counter_overflow_id:1092{1093Register bci = rax, method = rbx;1094__ enter();1095OopMap* map = save_live_registers(sasm, 3);1096// Retrieve bci1097__ movl(bci, Address(rbp, 2*BytesPerWord));1098// And a pointer to the Method*1099__ movptr(method, Address(rbp, 3*BytesPerWord));1100int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);1101oop_maps = new OopMapSet();1102oop_maps->add_gc_map(call_offset, map);1103restore_live_registers(sasm);1104__ leave();1105__ ret(0);1106}1107break;11081109case new_type_array_id:1110case new_object_array_id:1111{1112Register length = rbx; // Incoming1113Register klass = rdx; // Incoming1114Register obj = rax; // Result11151116if (id == new_type_array_id) {1117__ set_info("new_type_array", dont_gc_arguments);1118} else {1119__ set_info("new_object_array", dont_gc_arguments);1120}11211122#ifdef ASSERT1123// assert object type is really an array of the proper kind1124{1125Label ok;1126Register t0 = obj;1127__ movl(t0, Address(klass, Klass::layout_helper_offset()));1128__ sarl(t0, Klass::_lh_array_tag_shift);1129int tag = ((id == new_type_array_id)1130? Klass::_lh_array_tag_type_value1131: Klass::_lh_array_tag_obj_value);1132__ cmpl(t0, tag);1133__ jcc(Assembler::equal, ok);1134__ stop("assert(is an array klass)");1135__ should_not_reach_here();1136__ bind(ok);1137}1138#endif // ASSERT11391140if (UseTLAB && FastTLABRefill) {1141Register arr_size = rsi;1142Register t1 = rcx; // must be rcx for use as shift count1143Register t2 = rdi;1144Label slow_path;1145assert_different_registers(length, klass, obj, arr_size, t1, t2);11461147// check that array length is small enough for fast path.1148__ cmpl(length, C1_MacroAssembler::max_array_allocation_length);1149__ jcc(Assembler::above, slow_path);11501151// if we got here then the TLAB allocation failed, so try1152// refilling the TLAB or allocating directly from eden.1153Label retry_tlab, try_eden;1154const Register thread =1155__ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx & rdx, returns rdi11561157__ bind(retry_tlab);11581159// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))1160// since size is positive movl does right thing on 64bit1161__ movl(t1, Address(klass, Klass::layout_helper_offset()));1162// since size is postive movl does right thing on 64bit1163__ movl(arr_size, length);1164assert(t1 == rcx, "fixed register usage");1165__ shlptr(arr_size /* by t1=rcx, mod 32 */);1166__ shrptr(t1, Klass::_lh_header_size_shift);1167__ andptr(t1, Klass::_lh_header_size_mask);1168__ addptr(arr_size, t1);1169__ addptr(arr_size, MinObjAlignmentInBytesMask); // align up1170__ andptr(arr_size, ~MinObjAlignmentInBytesMask);11711172__ tlab_allocate(obj, arr_size, 0, t1, t2, slow_path); // preserves arr_size11731174__ initialize_header(obj, klass, length, t1, t2);1175__ movb(t1, Address(klass, in_bytes(Klass::layout_helper_offset()) + (Klass::_lh_header_size_shift / BitsPerByte)));1176assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");1177assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");1178__ andptr(t1, Klass::_lh_header_size_mask);1179__ subptr(arr_size, t1); // body length1180__ addptr(t1, obj); // body start1181__ initialize_body(t1, arr_size, 0, t2);1182__ verify_oop(obj);1183__ ret(0);11841185__ bind(try_eden);1186// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))1187// since size is positive movl does right thing on 64bit1188__ movl(t1, Address(klass, Klass::layout_helper_offset()));1189// since size is postive movl does right thing on 64bit1190__ movl(arr_size, length);1191assert(t1 == rcx, "fixed register usage");1192__ shlptr(arr_size /* by t1=rcx, mod 32 */);1193__ shrptr(t1, Klass::_lh_header_size_shift);1194__ andptr(t1, Klass::_lh_header_size_mask);1195__ addptr(arr_size, t1);1196__ addptr(arr_size, MinObjAlignmentInBytesMask); // align up1197__ andptr(arr_size, ~MinObjAlignmentInBytesMask);11981199__ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size1200__ incr_allocated_bytes(thread, arr_size, 0);12011202__ initialize_header(obj, klass, length, t1, t2);1203__ movb(t1, Address(klass, in_bytes(Klass::layout_helper_offset()) + (Klass::_lh_header_size_shift / BitsPerByte)));1204assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");1205assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");1206__ andptr(t1, Klass::_lh_header_size_mask);1207__ subptr(arr_size, t1); // body length1208__ addptr(t1, obj); // body start1209__ initialize_body(t1, arr_size, 0, t2);1210__ verify_oop(obj);1211__ ret(0);12121213__ bind(slow_path);1214}12151216__ enter();1217OopMap* map = save_live_registers(sasm, 3);1218int call_offset;1219if (id == new_type_array_id) {1220call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);1221} else {1222call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);1223}12241225oop_maps = new OopMapSet();1226oop_maps->add_gc_map(call_offset, map);1227restore_live_registers_except_rax(sasm);12281229__ verify_oop(obj);1230__ leave();1231__ ret(0);12321233// rax,: new array1234}1235break;12361237case new_multi_array_id:1238{ StubFrame f(sasm, "new_multi_array", dont_gc_arguments);1239// rax,: klass1240// rbx,: rank1241// rcx: address of 1st dimension1242OopMap* map = save_live_registers(sasm, 4);1243int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx);12441245oop_maps = new OopMapSet();1246oop_maps->add_gc_map(call_offset, map);1247restore_live_registers_except_rax(sasm);12481249// rax,: new multi array1250__ verify_oop(rax);1251}1252break;12531254case register_finalizer_id:1255{1256__ set_info("register_finalizer", dont_gc_arguments);12571258// This is called via call_runtime so the arguments1259// will be place in C abi locations12601261#ifdef _LP641262__ verify_oop(c_rarg0);1263__ mov(rax, c_rarg0);1264#else1265// The object is passed on the stack and we haven't pushed a1266// frame yet so it's one work away from top of stack.1267__ movptr(rax, Address(rsp, 1 * BytesPerWord));1268__ verify_oop(rax);1269#endif // _LP6412701271// load the klass and check the has finalizer flag1272Label register_finalizer;1273Register t = rsi;1274__ load_klass(t, rax);1275__ movl(t, Address(t, Klass::access_flags_offset()));1276__ testl(t, JVM_ACC_HAS_FINALIZER);1277__ jcc(Assembler::notZero, register_finalizer);1278__ ret(0);12791280__ bind(register_finalizer);1281__ enter();1282OopMap* oop_map = save_live_registers(sasm, 2 /*num_rt_args */);1283int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), rax);1284oop_maps = new OopMapSet();1285oop_maps->add_gc_map(call_offset, oop_map);12861287// Now restore all the live registers1288restore_live_registers(sasm);12891290__ leave();1291__ ret(0);1292}1293break;12941295case throw_range_check_failed_id:1296{ StubFrame f(sasm, "range_check_failed", dont_gc_arguments);1297oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true);1298}1299break;13001301case throw_index_exception_id:1302{ StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments);1303oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true);1304}1305break;13061307case throw_div0_exception_id:1308{ StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments);1309oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false);1310}1311break;13121313case throw_null_pointer_exception_id:1314{ StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments);1315oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false);1316}1317break;13181319case handle_exception_nofpu_id:1320case handle_exception_id:1321{ StubFrame f(sasm, "handle_exception", dont_gc_arguments);1322oop_maps = generate_handle_exception(id, sasm);1323}1324break;13251326case handle_exception_from_callee_id:1327{ StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments);1328oop_maps = generate_handle_exception(id, sasm);1329}1330break;13311332case unwind_exception_id:1333{ __ set_info("unwind_exception", dont_gc_arguments);1334// note: no stubframe since we are about to leave the current1335// activation and we are calling a leaf VM function only.1336generate_unwind_exception(sasm);1337}1338break;13391340case throw_array_store_exception_id:1341{ StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments);1342// tos + 0: link1343// + 1: return address1344oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);1345}1346break;13471348case throw_class_cast_exception_id:1349{ StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments);1350oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);1351}1352break;13531354case throw_incompatible_class_change_error_id:1355{ StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments);1356oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);1357}1358break;13591360case slow_subtype_check_id:1361{1362// Typical calling sequence:1363// __ push(klass_RInfo); // object klass or other subclass1364// __ push(sup_k_RInfo); // array element klass or other superclass1365// __ call(slow_subtype_check);1366// Note that the subclass is pushed first, and is therefore deepest.1367// Previous versions of this code reversed the names 'sub' and 'super'.1368// This was operationally harmless but made the code unreadable.1369enum layout {1370rax_off, SLOT2(raxH_off)1371rcx_off, SLOT2(rcxH_off)1372rsi_off, SLOT2(rsiH_off)1373rdi_off, SLOT2(rdiH_off)1374// saved_rbp_off, SLOT2(saved_rbpH_off)1375return_off, SLOT2(returnH_off)1376sup_k_off, SLOT2(sup_kH_off)1377klass_off, SLOT2(superH_off)1378framesize,1379result_off = klass_off // deepest argument is also the return value1380};13811382__ set_info("slow_subtype_check", dont_gc_arguments);1383__ push(rdi);1384__ push(rsi);1385__ push(rcx);1386__ push(rax);13871388// This is called by pushing args and not with C abi1389__ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass1390__ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass13911392Label miss;1393__ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss);13941395// fallthrough on success:1396__ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result1397__ pop(rax);1398__ pop(rcx);1399__ pop(rsi);1400__ pop(rdi);1401__ ret(0);14021403__ bind(miss);1404__ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result1405__ pop(rax);1406__ pop(rcx);1407__ pop(rsi);1408__ pop(rdi);1409__ ret(0);1410}1411break;14121413case monitorenter_nofpu_id:1414save_fpu_registers = false;1415// fall through1416case monitorenter_id:1417{1418StubFrame f(sasm, "monitorenter", dont_gc_arguments);1419OopMap* map = save_live_registers(sasm, 3, save_fpu_registers);14201421// Called with store_parameter and not C abi14221423f.load_argument(1, rax); // rax,: object1424f.load_argument(0, rbx); // rbx,: lock address14251426int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), rax, rbx);14271428oop_maps = new OopMapSet();1429oop_maps->add_gc_map(call_offset, map);1430restore_live_registers(sasm, save_fpu_registers);1431}1432break;14331434case monitorexit_nofpu_id:1435save_fpu_registers = false;1436// fall through1437case monitorexit_id:1438{1439StubFrame f(sasm, "monitorexit", dont_gc_arguments);1440OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);14411442// Called with store_parameter and not C abi14431444f.load_argument(0, rax); // rax,: lock address14451446// note: really a leaf routine but must setup last java sp1447// => use call_RT for now (speed can be improved by1448// doing last java sp setup manually)1449int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), rax);14501451oop_maps = new OopMapSet();1452oop_maps->add_gc_map(call_offset, map);1453restore_live_registers(sasm, save_fpu_registers);1454}1455break;14561457case deoptimize_id:1458{1459StubFrame f(sasm, "deoptimize", dont_gc_arguments);1460const int num_rt_args = 1; // thread1461OopMap* oop_map = save_live_registers(sasm, num_rt_args);1462int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, deoptimize));1463oop_maps = new OopMapSet();1464oop_maps->add_gc_map(call_offset, oop_map);1465restore_live_registers(sasm);1466DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();1467assert(deopt_blob != NULL, "deoptimization blob must have been created");1468__ leave();1469__ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution()));1470}1471break;14721473case access_field_patching_id:1474{ StubFrame f(sasm, "access_field_patching", dont_gc_arguments);1475// we should set up register map1476oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching));1477}1478break;14791480case load_klass_patching_id:1481{ StubFrame f(sasm, "load_klass_patching", dont_gc_arguments);1482// we should set up register map1483oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching));1484}1485break;14861487case load_mirror_patching_id:1488{ StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments);1489// we should set up register map1490oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching));1491}1492break;14931494case load_appendix_patching_id:1495{ StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments);1496// we should set up register map1497oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching));1498}1499break;15001501case dtrace_object_alloc_id:1502{ // rax,: object1503StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments);1504// we can't gc here so skip the oopmap but make sure that all1505// the live registers get saved.1506save_live_registers(sasm, 1);15071508__ NOT_LP64(push(rax)) LP64_ONLY(mov(c_rarg0, rax));1509__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc)));1510NOT_LP64(__ pop(rax));15111512restore_live_registers(sasm);1513}1514break;15151516case fpu2long_stub_id:1517{1518// rax, and rdx are destroyed, but should be free since the result is returned there1519// preserve rsi,ecx1520__ push(rsi);1521__ push(rcx);1522LP64_ONLY(__ push(rdx);)15231524// check for NaN1525Label return0, do_return, return_min_jlong, do_convert;15261527Address value_high_word(rsp, wordSize + 4);1528Address value_low_word(rsp, wordSize);1529Address result_high_word(rsp, 3*wordSize + 4);1530Address result_low_word(rsp, 3*wordSize);15311532__ subptr(rsp, 32); // more than enough on 32bit1533__ fst_d(value_low_word);1534__ movl(rax, value_high_word);1535__ andl(rax, 0x7ff00000);1536__ cmpl(rax, 0x7ff00000);1537__ jcc(Assembler::notEqual, do_convert);1538__ movl(rax, value_high_word);1539__ andl(rax, 0xfffff);1540__ orl(rax, value_low_word);1541__ jcc(Assembler::notZero, return0);15421543__ bind(do_convert);1544__ fnstcw(Address(rsp, 0));1545__ movzwl(rax, Address(rsp, 0));1546__ orl(rax, 0xc00);1547__ movw(Address(rsp, 2), rax);1548__ fldcw(Address(rsp, 2));1549__ fwait();1550__ fistp_d(result_low_word);1551__ fldcw(Address(rsp, 0));1552__ fwait();1553// This gets the entire long in rax on 64bit1554__ movptr(rax, result_low_word);1555// testing of high bits1556__ movl(rdx, result_high_word);1557__ mov(rcx, rax);1558// What the heck is the point of the next instruction???1559__ xorl(rcx, 0x0);1560__ movl(rsi, 0x80000000);1561__ xorl(rsi, rdx);1562__ orl(rcx, rsi);1563__ jcc(Assembler::notEqual, do_return);1564__ fldz();1565__ fcomp_d(value_low_word);1566__ fnstsw_ax();1567#ifdef _LP641568__ testl(rax, 0x4100); // ZF & CF == 01569__ jcc(Assembler::equal, return_min_jlong);1570#else1571__ sahf();1572__ jcc(Assembler::above, return_min_jlong);1573#endif // _LP641574// return max_jlong1575#ifndef _LP641576__ movl(rdx, 0x7fffffff);1577__ movl(rax, 0xffffffff);1578#else1579__ mov64(rax, CONST64(0x7fffffffffffffff));1580#endif // _LP641581__ jmp(do_return);15821583__ bind(return_min_jlong);1584#ifndef _LP641585__ movl(rdx, 0x80000000);1586__ xorl(rax, rax);1587#else1588__ mov64(rax, CONST64(0x8000000000000000));1589#endif // _LP641590__ jmp(do_return);15911592__ bind(return0);1593__ fpop();1594#ifndef _LP641595__ xorptr(rdx,rdx);1596__ xorptr(rax,rax);1597#else1598__ xorptr(rax, rax);1599#endif // _LP6416001601__ bind(do_return);1602__ addptr(rsp, 32);1603LP64_ONLY(__ pop(rdx);)1604__ pop(rcx);1605__ pop(rsi);1606__ ret(0);1607}1608break;16091610#if INCLUDE_ALL_GCS1611case g1_pre_barrier_slow_id:1612{1613StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);1614// arg0 : previous value of memory16151616BarrierSet* bs = Universe::heap()->barrier_set();1617if (bs->kind() != BarrierSet::G1SATBCTLogging) {1618__ movptr(rax, (int)id);1619__ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);1620__ should_not_reach_here();1621break;1622}1623__ push(rax);1624__ push(rdx);16251626const Register pre_val = rax;1627const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);1628const Register tmp = rdx;16291630NOT_LP64(__ get_thread(thread);)16311632Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +1633PtrQueue::byte_offset_of_active()));16341635Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +1636PtrQueue::byte_offset_of_index()));1637Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +1638PtrQueue::byte_offset_of_buf()));163916401641Label done;1642Label runtime;16431644// Can we store original value in the thread's buffer?16451646#ifdef _LP641647__ movslq(tmp, queue_index);1648__ cmpq(tmp, 0);1649#else1650__ cmpl(queue_index, 0);1651#endif1652__ jcc(Assembler::equal, runtime);1653#ifdef _LP641654__ subq(tmp, wordSize);1655__ movl(queue_index, tmp);1656__ addq(tmp, buffer);1657#else1658__ subl(queue_index, wordSize);1659__ movl(tmp, buffer);1660__ addl(tmp, queue_index);1661#endif16621663// prev_val (rax)1664f.load_argument(0, pre_val);1665__ movptr(Address(tmp, 0), pre_val);1666__ jmp(done);16671668__ bind(runtime);16691670save_live_registers(sasm, 3);16711672// load the pre-value1673f.load_argument(0, rcx);1674__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread);16751676restore_live_registers(sasm);16771678__ bind(done);16791680__ pop(rdx);1681__ pop(rax);1682}1683break;16841685case g1_post_barrier_slow_id:1686{1687StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);168816891690// arg0: store_address1691Address store_addr(rbp, 2*BytesPerWord);16921693BarrierSet* bs = Universe::heap()->barrier_set();1694CardTableModRefBS* ct = (CardTableModRefBS*)bs;1695assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");16961697Label done;1698Label runtime;16991700// At this point we know new_value is non-NULL and the new_value crosses regions.1701// Must check to see if card is already dirty17021703const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);17041705Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +1706PtrQueue::byte_offset_of_index()));1707Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +1708PtrQueue::byte_offset_of_buf()));17091710__ push(rax);1711__ push(rcx);17121713const Register cardtable = rax;1714const Register card_addr = rcx;17151716f.load_argument(0, card_addr);1717__ shrptr(card_addr, CardTableModRefBS::card_shift);1718// Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT1719// a valid address and therefore is not properly handled by the relocation code.1720__ movptr(cardtable, (intptr_t)ct->byte_map_base);1721__ addptr(card_addr, cardtable);17221723NOT_LP64(__ get_thread(thread);)17241725__ cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val());1726__ jcc(Assembler::equal, done);17271728__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));1729__ cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());1730__ jcc(Assembler::equal, done);17311732// storing region crossing non-NULL, card is clean.1733// dirty card and log.17341735__ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());17361737__ cmpl(queue_index, 0);1738__ jcc(Assembler::equal, runtime);1739__ subl(queue_index, wordSize);17401741const Register buffer_addr = rbx;1742__ push(rbx);17431744__ movptr(buffer_addr, buffer);17451746#ifdef _LP641747__ movslq(rscratch1, queue_index);1748__ addptr(buffer_addr, rscratch1);1749#else1750__ addptr(buffer_addr, queue_index);1751#endif1752__ movptr(Address(buffer_addr, 0), card_addr);17531754__ pop(rbx);1755__ jmp(done);17561757__ bind(runtime);1758__ push(rdx);17591760save_live_registers(sasm, 3);17611762__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);17631764restore_live_registers(sasm);17651766__ pop(rdx);1767__ bind(done);17681769__ pop(rcx);1770__ pop(rax);17711772}1773break;1774#endif // INCLUDE_ALL_GCS17751776case predicate_failed_trap_id:1777{1778StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments);17791780OopMap* map = save_live_registers(sasm, 1);17811782int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap));1783oop_maps = new OopMapSet();1784oop_maps->add_gc_map(call_offset, map);1785restore_live_registers(sasm);1786__ leave();1787DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();1788assert(deopt_blob != NULL, "deoptimization blob must have been created");17891790__ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution()));1791}1792break;17931794default:1795{ StubFrame f(sasm, "unimplemented entry", dont_gc_arguments);1796__ movptr(rax, (int)id);1797__ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);1798__ should_not_reach_here();1799}1800break;1801}1802return oop_maps;1803}18041805#undef __18061807const char *Runtime1::pd_name_for_address(address entry) {1808return "<unknown function>";1809}181018111812