c1_Runtime1_x86.cpp revision 0:a61af66fc99e
155682Smarkm/* 2233294Sstas * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. 3233294Sstas * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4233294Sstas * 555682Smarkm * This code is free software; you can redistribute it and/or modify it 6233294Sstas * under the terms of the GNU General Public License version 2 only, as 7233294Sstas * published by the Free Software Foundation. 8233294Sstas * 955682Smarkm * This code is distributed in the hope that it will be useful, but WITHOUT 10233294Sstas * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11233294Sstas * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1255682Smarkm * version 2 for more details (a copy is included in the LICENSE file that 13233294Sstas * accompanied this code). 14233294Sstas * 15233294Sstas * You should have received a copy of the GNU General Public License version 1655682Smarkm * 2 along with this work; if not, write to the Free Software Foundation, 17233294Sstas * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18233294Sstas * 19233294Sstas * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2055682Smarkm * CA 95054 USA or visit www.sun.com if you need additional information or 21233294Sstas * have any questions. 22233294Sstas * 23233294Sstas */ 24233294Sstas 25233294Sstas#include "incls/_precompiled.incl" 26233294Sstas#include "incls/_c1_Runtime1_x86.cpp.incl" 27233294Sstas 28233294Sstas 29233294Sstas// Implementation of StubAssembler 30233294Sstas 31233294Sstasint StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, int args_size) { 3255682Smarkm // setup registers 3355682Smarkm const Register thread = rdi; // is callee-saved register (Visual C++ calling conventions) 3455682Smarkm assert(!(oop_result1->is_valid() || oop_result2->is_valid()) || oop_result1 != oop_result2, "registers must be different"); 35178825Sdfr assert(oop_result1 != thread && oop_result2 != thread, "registers must be different"); 3655682Smarkm assert(args_size >= 0, "illegal args_size"); 37233294Sstas 3855682Smarkm set_num_rt_args(1 + args_size); 3955682Smarkm 4055682Smarkm // push java thread (becomes first argument of C function) 4155682Smarkm get_thread(thread); 4255682Smarkm pushl(thread); 4355682Smarkm 4455682Smarkm set_last_Java_frame(thread, noreg, rbp, NULL); 4555682Smarkm // do the call 4655682Smarkm call(RuntimeAddress(entry)); 4755682Smarkm int call_offset = offset(); 4855682Smarkm // verify callee-saved register 4955682Smarkm#ifdef ASSERT 5055682Smarkm guarantee(thread != rax, "change this code"); 5155682Smarkm pushl(rax); 5255682Smarkm { Label L; 5372445Sassar get_thread(rax); 54178825Sdfr cmpl(thread, rax); 5555682Smarkm jcc(Assembler::equal, L); 5655682Smarkm int3(); 5755682Smarkm stop("StubAssembler::call_RT: rdi not callee saved?"); 5855682Smarkm bind(L); 5955682Smarkm } 6055682Smarkm popl(rax); 6155682Smarkm#endif 6255682Smarkm reset_last_Java_frame(thread, true, false); 6355682Smarkm 6455682Smarkm // discard thread and arguments 6555682Smarkm addl(rsp, (1 + args_size)*BytesPerWord); 6655682Smarkm 6755682Smarkm // check for pending exceptions 68102644Snectar { Label L; 6955682Smarkm cmpl(Address(thread, Thread::pending_exception_offset()), NULL_WORD); 7055682Smarkm jcc(Assembler::equal, L); 7155682Smarkm // exception pending => remove activation and forward to exception handler 7255682Smarkm movl(rax, Address(thread, Thread::pending_exception_offset())); 7355682Smarkm // make sure that the vm_results are cleared 7455682Smarkm if (oop_result1->is_valid()) { 7555682Smarkm movl(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 7655682Smarkm } 77178825Sdfr if (oop_result2->is_valid()) { 7872445Sassar movl(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); 7972445Sassar } 8072445Sassar if (frame_size() == no_frame_size) { 8172445Sassar leave(); 8272445Sassar jump(RuntimeAddress(StubRoutines::forward_exception_entry())); 83178825Sdfr } else if (_stub_id == Runtime1::forward_exception_id) { 8472445Sassar should_not_reach_here(); 8572445Sassar } else { 8672445Sassar jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); 8772445Sassar } 8872445Sassar bind(L); 8972445Sassar } 9072445Sassar // get oop results if there are any and reset the values in the thread 9172445Sassar if (oop_result1->is_valid()) { 9255682Smarkm movl(oop_result1, Address(thread, JavaThread::vm_result_offset())); 9355682Smarkm movl(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 9455682Smarkm verify_oop(oop_result1); 9555682Smarkm } 9655682Smarkm if (oop_result2->is_valid()) { 9755682Smarkm movl(oop_result2, Address(thread, JavaThread::vm_result_2_offset())); 9855682Smarkm movl(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); 9955682Smarkm verify_oop(oop_result2); 10055682Smarkm } 101178825Sdfr return call_offset; 102233294Sstas} 103233294Sstas 104178825Sdfr 105233294Sstasint StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1) { 106178825Sdfr pushl(arg1); 10755682Smarkm return call_RT(oop_result1, oop_result2, entry, 1); 108233294Sstas} 109233294Sstas 110233294Sstas 11155682Smarkmint StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1, Register arg2) { 11255682Smarkm pushl(arg2); 11355682Smarkm pushl(arg1); 11455682Smarkm return call_RT(oop_result1, oop_result2, entry, 2); 11572445Sassar} 11655682Smarkm 11755682Smarkm 11855682Smarkmint StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1, Register arg2, Register arg3) { 11955682Smarkm pushl(arg3); 12055682Smarkm pushl(arg2); 12155682Smarkm pushl(arg1); 12255682Smarkm return call_RT(oop_result1, oop_result2, entry, 3); 12355682Smarkm} 12472445Sassar 12572445Sassar 12672445Sassar// Implementation of StubFrame 12772445Sassar 12872445Sassarclass StubFrame: public StackObj { 12972445Sassar private: 130178825Sdfr StubAssembler* _sasm; 13172445Sassar 13272445Sassar public: 13372445Sassar StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments); 13472445Sassar void load_argument(int offset_in_words, Register reg); 13572445Sassar 13672445Sassar ~StubFrame(); 13772445Sassar}; 13872445Sassar 13972445Sassar 14072445Sassar#define __ _sasm-> 14172445Sassar 14272445SassarStubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { 14372445Sassar _sasm = sasm; 14472445Sassar __ set_info(name, must_gc_arguments); 14572445Sassar __ enter(); 14672445Sassar} 14772445Sassar 14872445Sassar// load parameters that were stored with LIR_Assembler::store_parameter 14955682Smarkm// Note: offsets for store_parameter and load_argument must match 15055682Smarkmvoid StubFrame::load_argument(int offset_in_words, Register reg) { 15155682Smarkm // rbp, + 0: link 15255682Smarkm // + 1: return address 15355682Smarkm // + 2: argument with offset 0 15455682Smarkm // + 3: argument with offset 1 15555682Smarkm // + 4: ... 15655682Smarkm 15755682Smarkm __ movl(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord)); 15855682Smarkm} 15955682Smarkm 16055682Smarkm 16155682SmarkmStubFrame::~StubFrame() { 16255682Smarkm __ leave(); 16355682Smarkm __ ret(0); 16455682Smarkm} 16555682Smarkm 16655682Smarkm#undef __ 16755682Smarkm 16855682Smarkm 16955682Smarkm// Implementation of Runtime1 17055682Smarkm 17155682Smarkm#define __ sasm-> 17255682Smarkm 17355682Smarkmconst int float_regs_as_doubles_size_in_words = 16; 17455682Smarkmconst int xmm_regs_as_doubles_size_in_words = 16; 17555682Smarkm 17655682Smarkm// Stack layout for saving/restoring all the registers needed during a runtime 17755682Smarkm// call (this includes deoptimization) 17855682Smarkm// Note: note that users of this frame may well have arguments to some runtime 17955682Smarkm// while these values are on the stack. These positions neglect those arguments 18055682Smarkm// but the code in save_live_registers will take the argument count into 18155682Smarkm// account. 18255682Smarkm// 18355682Smarkmenum reg_save_layout { 18455682Smarkm dummy1, 18555682Smarkm dummy2, 18655682Smarkm // Two temps to be used as needed by users of save/restore callee registers 18755682Smarkm temp_2_off, 18855682Smarkm temp_1_off, 18955682Smarkm xmm_regs_as_doubles_off, 19055682Smarkm float_regs_as_doubles_off = xmm_regs_as_doubles_off + xmm_regs_as_doubles_size_in_words, 19155682Smarkm fpu_state_off = float_regs_as_doubles_off + float_regs_as_doubles_size_in_words, 19255682Smarkm fpu_state_end_off = fpu_state_off + FPUStateSizeInWords, 19355682Smarkm marker = fpu_state_end_off, 19455682Smarkm extra_space_offset, 19555682Smarkm rdi_off = extra_space_offset, 196233294Sstas rsi_off, 19755682Smarkm rbp_off, 19855682Smarkm rsp_off, 19955682Smarkm rbx_off, 20055682Smarkm rdx_off, 201233294Sstas rcx_off, 20255682Smarkm rax_off, 20355682Smarkm saved_rbp_off, 20455682Smarkm return_off, 20555682Smarkm reg_save_frame_size, // As noted: neglects any parameters to runtime 20655682Smarkm 20755682Smarkm // equates 20855682Smarkm 209233294Sstas // illegal instruction handler 21055682Smarkm continue_dest_off = temp_1_off, 21155682Smarkm 21255682Smarkm // deoptimization equates 213233294Sstas fp0_off = float_regs_as_doubles_off, // slot for java float/double return value 21455682Smarkm xmm0_off = xmm_regs_as_doubles_off, // slot for java float/double return value 21555682Smarkm deopt_type = temp_2_off, // slot for type of deopt in progress 21655682Smarkm ret_type = temp_1_off // slot for return type 21755682Smarkm}; 21855682Smarkm 21955682Smarkm 220233294Sstas 221233294Sstas// Save off registers which might be killed by calls into the runtime. 222233294Sstas// Tries to smart of about FP registers. In particular we separate 223233294Sstas// saving and describing the FPU registers for deoptimization since we 224233294Sstas// have to save the FPU registers twice if we describe them and on P4 225233294Sstas// saving FPU registers which don't contain anything appears 226233294Sstas// expensive. The deopt blob is the only thing which needs to 227233294Sstas// describe FPU registers. In all other cases it should be sufficient 22855682Smarkm// to simply save their current value. 22955682Smarkm 23055682Smarkmstatic OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, 23155682Smarkm bool save_fpu_registers = true) { 23255682Smarkm int frame_size = reg_save_frame_size + num_rt_args; // args + thread 23355682Smarkm sasm->set_frame_size(frame_size); 23455682Smarkm 23555682Smarkm // record saved value locations in an OopMap 23655682Smarkm // locations are offsets from sp after runtime call; num_rt_args is number of arguments in call, including thread 23755682Smarkm OopMap* map = new OopMap(frame_size, 0); 23855682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(rax_off + num_rt_args), rax->as_VMReg()); 23955682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(rcx_off + num_rt_args), rcx->as_VMReg()); 24055682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(rdx_off + num_rt_args), rdx->as_VMReg()); 24155682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg()); 24255682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg()); 24355682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg()); 24455682Smarkm 24555682Smarkm if (save_fpu_registers) { 24655682Smarkm if (UseSSE < 2) { 24755682Smarkm int fpu_off = float_regs_as_doubles_off; 24855682Smarkm for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { 24955682Smarkm VMReg fpu_name_0 = FrameMap::fpu_regname(n); 25055682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + num_rt_args), fpu_name_0); 25155682Smarkm // %%% This is really a waste but we'll keep things as they were for now 25255682Smarkm if (true) { 25355682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + 1 + num_rt_args), fpu_name_0->next()); 25455682Smarkm } 25555682Smarkm fpu_off += 2; 25655682Smarkm } 25755682Smarkm assert(fpu_off == fpu_state_off, "incorrect number of fpu stack slots"); 25855682Smarkm } 259102644Snectar 26055682Smarkm if (UseSSE >= 2) { 26155682Smarkm int xmm_off = xmm_regs_as_doubles_off; 26255682Smarkm for (int n = 0; n < FrameMap::nof_xmm_regs; n++) { 26355682Smarkm VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg(); 26455682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0); 26555682Smarkm // %%% This is really a waste but we'll keep things as they were for now 26655682Smarkm if (true) { 26755682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + 1 + num_rt_args), xmm_name_0->next()); 26855682Smarkm } 26955682Smarkm xmm_off += 2; 27055682Smarkm } 27155682Smarkm assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers"); 27255682Smarkm 27355682Smarkm } else if (UseSSE == 1) { 27455682Smarkm int xmm_off = xmm_regs_as_doubles_off; 27555682Smarkm for (int n = 0; n < FrameMap::nof_xmm_regs; n++) { 27655682Smarkm VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg(); 27755682Smarkm map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0); 27855682Smarkm xmm_off += 2; 27955682Smarkm } 280178825Sdfr assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers"); 28155682Smarkm } 282178825Sdfr } 283178825Sdfr 28455682Smarkm return map; 28555682Smarkm} 28655682Smarkm 28755682Smarkmstatic OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args, 288178825Sdfr bool save_fpu_registers = true) { 28955682Smarkm __ block_comment("save_live_registers"); 290178825Sdfr 291178825Sdfr int frame_size = reg_save_frame_size + num_rt_args; // args + thread 292120945Snectar // frame_size = round_to(frame_size, 4); 293178825Sdfr sasm->set_frame_size(frame_size); 294233294Sstas 295120945Snectar __ pushad(); // integer registers 296178825Sdfr 297102644Snectar // assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset"); 298178825Sdfr // assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset"); 29955682Smarkm 300178825Sdfr __ subl(rsp, extra_space_offset * wordSize); 301233294Sstas 302233294Sstas#ifdef ASSERT 30355682Smarkm __ movl(Address(rsp, marker * wordSize), 0xfeedbeef); 304178825Sdfr#endif 305178825Sdfr 30655682Smarkm if (save_fpu_registers) { 30755682Smarkm if (UseSSE < 2) { 30855682Smarkm // save FPU stack 30955682Smarkm __ fnsave(Address(rsp, fpu_state_off * wordSize)); 31055682Smarkm __ fwait(); 31155682Smarkm 31255682Smarkm#ifdef ASSERT 31355682Smarkm Label ok; 31455682Smarkm __ cmpw(Address(rsp, fpu_state_off * wordSize), StubRoutines::fpu_cntrl_wrd_std()); 31555682Smarkm __ jccb(Assembler::equal, ok); 31655682Smarkm __ stop("corrupted control word detected"); 31755682Smarkm __ bind(ok); 31855682Smarkm#endif 31955682Smarkm 32055682Smarkm // Reset the control word to guard against exceptions being unmasked 32155682Smarkm // since fstp_d can cause FPU stack underflow exceptions. Write it 32255682Smarkm // into the on stack copy and then reload that to make sure that the 32355682Smarkm // current and future values are correct. 32455682Smarkm __ movw(Address(rsp, fpu_state_off * wordSize), StubRoutines::fpu_cntrl_wrd_std()); 325178825Sdfr __ frstor(Address(rsp, fpu_state_off * wordSize)); 326178825Sdfr 32755682Smarkm // Save the FPU registers in de-opt-able form 328178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 0)); 329178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 8)); 330178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 16)); 331178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 24)); 332178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 32)); 333102644Snectar __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 40)); 334178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 48)); 335178825Sdfr __ fstp_d(Address(rsp, float_regs_as_doubles_off * BytesPerWord + 56)); 336178825Sdfr } 337102644Snectar 338102644Snectar if (UseSSE >= 2) { 339178825Sdfr // save XMM registers 340178825Sdfr // XMM registers can contain float or double values, but this is not known here, 341178825Sdfr // so always save them as doubles. 342102644Snectar // note that float values are _not_ converted automatically, so for float values 343178825Sdfr // the second word contains only garbage data. 344178825Sdfr __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 0), xmm0); 345178825Sdfr __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 8), xmm1); 34655682Smarkm __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 16), xmm2); 347178825Sdfr __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 24), xmm3); 348178825Sdfr __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 32), xmm4); 34955682Smarkm __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 40), xmm5); 35055682Smarkm __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 48), xmm6); 351178825Sdfr __ movdbl(Address(rsp, xmm_regs_as_doubles_off * wordSize + 56), xmm7); 35255682Smarkm } else if (UseSSE == 1) { 353178825Sdfr // save XMM registers as float because double not supported without SSE2 354178825Sdfr __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 0), xmm0); 35555682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 8), xmm1); 35655682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 16), xmm2); 35755682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 24), xmm3); 35855682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 32), xmm4); 35955682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 40), xmm5); 36055682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 48), xmm6); 36155682Smarkm __ movflt(Address(rsp, xmm_regs_as_doubles_off * wordSize + 56), xmm7); 362178825Sdfr } 36355682Smarkm } 364178825Sdfr 365178825Sdfr // FPU stack must be empty now 36655682Smarkm __ verify_FPU(0, "save_live_registers"); 36755682Smarkm 36855682Smarkm return generate_oop_map(sasm, num_rt_args, save_fpu_registers); 369178825Sdfr} 37055682Smarkm 371178825Sdfr 372178825Sdfrstatic void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true) { 373233294Sstas if (restore_fpu_registers) { 374233294Sstas if (UseSSE >= 2) { 375178825Sdfr // restore XMM registers 376178825Sdfr __ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * wordSize + 0)); 37755682Smarkm __ movdbl(xmm1, Address(rsp, xmm_regs_as_doubles_off * wordSize + 8)); 378178825Sdfr __ movdbl(xmm2, Address(rsp, xmm_regs_as_doubles_off * wordSize + 16)); 379178825Sdfr __ movdbl(xmm3, Address(rsp, xmm_regs_as_doubles_off * wordSize + 24)); 38055682Smarkm __ movdbl(xmm4, Address(rsp, xmm_regs_as_doubles_off * wordSize + 32)); 38155682Smarkm __ movdbl(xmm5, Address(rsp, xmm_regs_as_doubles_off * wordSize + 40)); 38255682Smarkm __ movdbl(xmm6, Address(rsp, xmm_regs_as_doubles_off * wordSize + 48)); 38355682Smarkm __ movdbl(xmm7, Address(rsp, xmm_regs_as_doubles_off * wordSize + 56)); 38455682Smarkm } else if (UseSSE == 1) { 38555682Smarkm // restore XMM registers 38655682Smarkm __ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * wordSize + 0)); 38755682Smarkm __ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * wordSize + 8)); 38855682Smarkm __ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * wordSize + 16)); 38955682Smarkm __ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * wordSize + 24)); 39055682Smarkm __ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * wordSize + 32)); 39155682Smarkm __ movflt(xmm5, Address(rsp, xmm_regs_as_doubles_off * wordSize + 40)); 39255682Smarkm __ movflt(xmm6, Address(rsp, xmm_regs_as_doubles_off * wordSize + 48)); 39355682Smarkm __ movflt(xmm7, Address(rsp, xmm_regs_as_doubles_off * wordSize + 56)); 39455682Smarkm } 39555682Smarkm 39655682Smarkm if (UseSSE < 2) { 39755682Smarkm __ frstor(Address(rsp, fpu_state_off * wordSize)); 39855682Smarkm } else { 399178825Sdfr // check that FPU stack is really empty 400178825Sdfr __ verify_FPU(0, "restore_live_registers"); 40155682Smarkm } 40255682Smarkm 403178825Sdfr } else { 404178825Sdfr // check that FPU stack is really empty 405178825Sdfr __ verify_FPU(0, "restore_live_registers"); 40655682Smarkm } 407178825Sdfr 408178825Sdfr#ifdef ASSERT 409178825Sdfr { 410178825Sdfr Label ok; 411178825Sdfr __ cmpl(Address(rsp, marker * wordSize), 0xfeedbeef); 412178825Sdfr __ jcc(Assembler::equal, ok); 413102644Snectar __ stop("bad offsets in frame"); 414178825Sdfr __ bind(ok); 415178825Sdfr } 416178825Sdfr#endif 417178825Sdfr 418102644Snectar __ addl(rsp, extra_space_offset * wordSize); 419102644Snectar} 42055682Smarkm 421102644Snectar 422178825Sdfrstatic void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { 423178825Sdfr __ block_comment("restore_live_registers"); 424178825Sdfr 425178825Sdfr restore_fpu(sasm, restore_fpu_registers); 426102644Snectar __ popad(); 427178825Sdfr} 428178825Sdfr 429178825Sdfr 430178825Sdfrstatic void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) { 43155682Smarkm __ block_comment("restore_live_registers_except_rax"); 432178825Sdfr 433178825Sdfr restore_fpu(sasm, restore_fpu_registers); 434178825Sdfr 43555682Smarkm __ popl(rdi); 436178825Sdfr __ popl(rsi); 437178825Sdfr __ popl(rbp); 43855682Smarkm __ popl(rbx); // skip this value 439178825Sdfr __ popl(rbx); 440178825Sdfr __ popl(rdx); 441178825Sdfr __ popl(rcx); 442178825Sdfr __ addl(rsp, 4); 443178825Sdfr} 444178825Sdfr 445178825Sdfr 44655682Smarkmvoid Runtime1::initialize_pd() { 44755682Smarkm // nothing to do 44855682Smarkm} 44955682Smarkm 45055682Smarkm 45155682Smarkm// target: the entry point of the method that creates and posts the exception oop 45255682Smarkm// has_argument: true if the exception needs an argument (passed on stack because registers must be preserved) 453178825Sdfr 45455682SmarkmOopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { 455178825Sdfr // preserve all registers 456178825Sdfr int num_rt_args = has_argument ? 2 : 1; 45755682Smarkm OopMap* oop_map = save_live_registers(sasm, num_rt_args); 45855682Smarkm 45955682Smarkm // now all registers are saved and can be used freely 46055682Smarkm // verify that no old value is used accidentally 461178825Sdfr __ invalidate_registers(true, true, true, true, true, true); 46255682Smarkm 46355682Smarkm // registers used by this stub 46455682Smarkm const Register temp_reg = rbx; 46555682Smarkm 466178825Sdfr // load argument for exception that is passed as an argument into the stub 467178825Sdfr if (has_argument) { 468102644Snectar __ movl(temp_reg, Address(rbp, 2*BytesPerWord)); 469178825Sdfr __ pushl(temp_reg); 470178825Sdfr } 471233294Sstas 472233294Sstas int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1); 473178825Sdfr 474178825Sdfr OopMapSet* oop_maps = new OopMapSet(); 475102644Snectar oop_maps->add_gc_map(call_offset, oop_map); 47655682Smarkm 477120945Snectar __ stop("should not reach here"); 478120945Snectar 479120945Snectar return oop_maps; 480120945Snectar} 481120945Snectar 482102644Snectar 483178825Sdfrvoid Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map, bool save_fpu_registers) { 48455682Smarkm // incoming parameters 48555682Smarkm const Register exception_oop = rax; 48655682Smarkm const Register exception_pc = rdx; 48755682Smarkm // other registers used in this stub 48855682Smarkm const Register real_return_addr = rbx; 489233294Sstas const Register thread = rdi; 490178825Sdfr 49155682Smarkm __ block_comment("generate_handle_exception"); 49255682Smarkm 49355682Smarkm#ifdef TIERED 49455682Smarkm // C2 can leave the fpu stack dirty 49555682Smarkm if (UseSSE < 2 ) { 496178825Sdfr __ empty_FPU_stack(); 49755682Smarkm } 49855682Smarkm#endif // TIERED 49955682Smarkm 50055682Smarkm // verify that only rax, and rdx is valid at this time 50155682Smarkm __ invalidate_registers(false, true, true, false, true, true); 50255682Smarkm // verify that rax, contains a valid exception 50355682Smarkm __ verify_not_null_oop(exception_oop); 50455682Smarkm 50555682Smarkm // load address of JavaThread object for thread-local data 50655682Smarkm __ get_thread(thread); 50755682Smarkm 50855682Smarkm#ifdef ASSERT 509178825Sdfr // check that fields in JavaThread for exception oop and issuing pc are 51055682Smarkm // empty before writing to them 51155682Smarkm Label oop_empty; 51255682Smarkm __ cmpl(Address(thread, JavaThread::exception_oop_offset()), 0); 51355682Smarkm __ jcc(Assembler::equal, oop_empty); 514178825Sdfr __ stop("exception oop already set"); 51555682Smarkm __ bind(oop_empty); 51655682Smarkm 517178825Sdfr Label pc_empty; 518178825Sdfr __ cmpl(Address(thread, JavaThread::exception_pc_offset()), 0); 51955682Smarkm __ jcc(Assembler::equal, pc_empty); 52055682Smarkm __ stop("exception pc already set"); 521178825Sdfr __ bind(pc_empty); 522178825Sdfr#endif 523178825Sdfr 52455682Smarkm // save exception oop and issuing pc into JavaThread 525178825Sdfr // (exception handler will load it from here) 526178825Sdfr __ movl(Address(thread, JavaThread::exception_oop_offset()), exception_oop); 527178825Sdfr __ movl(Address(thread, JavaThread::exception_pc_offset()), exception_pc); 52855682Smarkm 529178825Sdfr // save real return address (pc that called this stub) 530178825Sdfr __ movl(real_return_addr, Address(rbp, 1*BytesPerWord)); 531178825Sdfr __ movl(Address(rsp, temp_1_off * BytesPerWord), real_return_addr); 532178825Sdfr 533178825Sdfr // patch throwing pc into return address (has bci & oop map) 534178825Sdfr __ movl(Address(rbp, 1*BytesPerWord), exception_pc); 535102644Snectar 536178825Sdfr // compute the exception handler. 537178825Sdfr // the exception oop and the throwing pc are read from the fields in JavaThread 538178825Sdfr int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); 539178825Sdfr oop_maps->add_gc_map(call_offset, oop_map); 54055682Smarkm 541178825Sdfr // rax,: handler address or NULL if no handler exists 542178825Sdfr // will be the deopt blob if nmethod was deoptimized while we looked up 54355682Smarkm // handler regardless of whether handler existed in the nmethod. 544178825Sdfr 545178825Sdfr // only rax, is valid at this time, all other registers have been destroyed by the runtime call 546178825Sdfr __ invalidate_registers(false, true, true, true, true, true); 54755682Smarkm 548178825Sdfr // Do we have an exception handler in the nmethod? 549178825Sdfr Label no_handler; 550178825Sdfr Label done; 551178825Sdfr __ testl(rax, rax); 55255682Smarkm __ jcc(Assembler::zero, no_handler); 55355682Smarkm 55455682Smarkm // exception handler found 55555682Smarkm // patch the return address -> the stub will directly return to the exception handler 55655682Smarkm __ movl(Address(rbp, 1*BytesPerWord), rax); 55755682Smarkm 55855682Smarkm // restore registers 559178825Sdfr restore_live_registers(sasm, save_fpu_registers); 56055682Smarkm 561178825Sdfr // return to exception handler 562178825Sdfr __ leave(); 56355682Smarkm __ ret(0); 56455682Smarkm 56555682Smarkm __ bind(no_handler); 56655682Smarkm // no exception handler found in this method, so the exception is 56755682Smarkm // forwarded to the caller (using the unwind code of the nmethod) 568178825Sdfr // there is no need to restore the registers 56955682Smarkm 570178825Sdfr // restore the real return address that was saved before the RT-call 571178825Sdfr __ movl(real_return_addr, Address(rsp, temp_1_off * BytesPerWord)); 57255682Smarkm __ movl(Address(rbp, 1*BytesPerWord), real_return_addr); 57355682Smarkm 574120945Snectar // load address of JavaThread object for thread-local data 575178825Sdfr __ get_thread(thread); 576233294Sstas // restore exception oop into rax, (convention for unwind code) 577120945Snectar __ movl(exception_oop, Address(thread, JavaThread::exception_oop_offset())); 578178825Sdfr 579102644Snectar // clear exception fields in JavaThread because they are no longer needed 580178825Sdfr // (fields must be cleared because they are processed by GC otherwise) 58155682Smarkm __ movl(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD); 58255682Smarkm __ movl(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD); 58355682Smarkm 584178825Sdfr // pop the stub frame off 585178825Sdfr __ leave(); 586233294Sstas 587233294Sstas generate_unwind_exception(sasm); 588233294Sstas __ stop("should not reach here"); 58955682Smarkm} 590178825Sdfr 59155682Smarkm 592178825Sdfrvoid Runtime1::generate_unwind_exception(StubAssembler *sasm) { 593178825Sdfr // incoming parameters 59472445Sassar const Register exception_oop = rax; 595178825Sdfr // other registers used in this stub 596178825Sdfr const Register exception_pc = rdx; 597178825Sdfr const Register handler_addr = rbx; 598178825Sdfr const Register thread = rdi; 599233294Sstas 600178825Sdfr // verify that only rax, is valid at this time 601178825Sdfr __ invalidate_registers(false, true, true, true, true, true); 602178825Sdfr 603178825Sdfr#ifdef ASSERT 60472445Sassar // check that fields in JavaThread for exception oop and issuing pc are empty 60555682Smarkm __ get_thread(thread); 60655682Smarkm Label oop_empty; 607178825Sdfr __ cmpl(Address(thread, JavaThread::exception_oop_offset()), 0); 608178825Sdfr __ jcc(Assembler::equal, oop_empty); 60972445Sassar __ stop("exception oop must be empty"); 610178825Sdfr __ bind(oop_empty); 611178825Sdfr 612178825Sdfr Label pc_empty; 613178825Sdfr __ cmpl(Address(thread, JavaThread::exception_pc_offset()), 0); 614233294Sstas __ jcc(Assembler::equal, pc_empty); 615178825Sdfr __ stop("exception pc must be empty"); 616178825Sdfr __ bind(pc_empty); 617178825Sdfr#endif 618178825Sdfr 61972445Sassar // clear the FPU stack in case any FPU results are left behind 62055682Smarkm __ empty_FPU_stack(); 62155682Smarkm 62255682Smarkm // leave activation of nmethod 62355682Smarkm __ leave(); 62455682Smarkm // store return address (is on top of stack after leave) 625178825Sdfr __ movl(exception_pc, Address(rsp, 0)); 62655682Smarkm 62755682Smarkm __ verify_oop(exception_oop); 628178825Sdfr 629178825Sdfr // save exception oop from rax, to stack before call 63072445Sassar __ pushl(exception_oop); 631178825Sdfr 632178825Sdfr // search the exception handler address of the caller (using the return address) 633178825Sdfr __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), exception_pc); 634178825Sdfr // rax,: exception handler address of the caller 635233294Sstas 636178825Sdfr // only rax, is valid at this time, all other registers have been destroyed by the call 637178825Sdfr __ invalidate_registers(false, true, true, true, true, true); 638178825Sdfr 639178825Sdfr // move result of call into correct register 64072445Sassar __ movl(handler_addr, rax); 64155682Smarkm 64255682Smarkm // restore exception oop in rax, (required convention of exception handler) 643178825Sdfr __ popl(exception_oop); 644178825Sdfr 645178825Sdfr __ verify_oop(exception_oop); 646178825Sdfr 647233294Sstas // get throwing pc (= return address). 648178825Sdfr // rdx has been destroyed by the call, so it must be set again 649178825Sdfr // the pop is also necessary to simulate the effect of a ret(0) 65055682Smarkm __ popl(exception_pc); 651178825Sdfr 652178825Sdfr // verify that that there is really a valid exception in rax, 653178825Sdfr __ verify_not_null_oop(exception_oop); 654233294Sstas 655178825Sdfr // continue at exception handler (return address removed) 656178825Sdfr // note: do *not* remove arguments when unwinding the 65755682Smarkm // activation since the caller assumes having 65855682Smarkm // all arguments on the stack when entering the 659178825Sdfr // runtime to determine the exception handler 66055682Smarkm // (GC happens at call site with arguments!) 66155682Smarkm // rax,: exception oop 66255682Smarkm // rdx: throwing pc 66355682Smarkm // rbx,: exception handler 66455682Smarkm __ jmp(handler_addr); 66555682Smarkm} 66655682Smarkm 66755682Smarkm 66855682SmarkmOopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { 66955682Smarkm // use the maximum number of runtime-arguments here because it is difficult to 67055682Smarkm // distinguish each RT-Call. 67155682Smarkm // Note: This number affects also the RT-Call in generate_handle_exception because 67255682Smarkm // the oop-map is shared for all calls. 67355682Smarkm const int num_rt_args = 2; // thread + dummy 674178825Sdfr 675178825Sdfr DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); 67672445Sassar assert(deopt_blob != NULL, "deoptimization blob must have been created"); 677178825Sdfr 678178825Sdfr OopMap* oop_map = save_live_registers(sasm, num_rt_args); 679178825Sdfr 680178825Sdfr __ pushl(rax); // push dummy 681233294Sstas 682178825Sdfr const Register thread = rdi; // is callee-saved register (Visual C++ calling conventions) 683178825Sdfr // push java thread (becomes first argument of C function) 684178825Sdfr __ get_thread(thread); 685178825Sdfr __ pushl(thread); 68672445Sassar __ set_last_Java_frame(thread, noreg, rbp, NULL); 68755682Smarkm // do the call 68855682Smarkm __ call(RuntimeAddress(target)); 68955682Smarkm OopMapSet* oop_maps = new OopMapSet(); 69055682Smarkm oop_maps->add_gc_map(__ offset(), oop_map); 69155682Smarkm // verify callee-saved register 69255682Smarkm#ifdef ASSERT 69355682Smarkm guarantee(thread != rax, "change this code"); 69455682Smarkm __ pushl(rax); 69555682Smarkm { Label L; 69655682Smarkm __ get_thread(rax); 69755682Smarkm __ cmpl(thread, rax); 698178825Sdfr __ jcc(Assembler::equal, L); 699233294Sstas __ stop("StubAssembler::call_RT: rdi not callee saved?"); 70055682Smarkm __ bind(L); 701178825Sdfr } 702178825Sdfr __ popl(rax); 703178825Sdfr#endif 70455682Smarkm __ reset_last_Java_frame(thread, true, false); 705178825Sdfr __ popl(rcx); // discard thread arg 70655682Smarkm __ popl(rcx); // discard dummy 707178825Sdfr 708178825Sdfr // check for pending exceptions 709178825Sdfr { Label L; 710233294Sstas __ cmpl(Address(thread, Thread::pending_exception_offset()), NULL_WORD); 711178825Sdfr __ jcc(Assembler::equal, L); 712178825Sdfr // exception pending => remove activation and forward to exception handler 713178825Sdfr 714178825Sdfr __ testl(rax, rax); // have we deoptimized? 715178825Sdfr __ jump_cc(Assembler::equal, 716178825Sdfr RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); 717233294Sstas 718178825Sdfr // the deopt blob expects exceptions in the special fields of 719178825Sdfr // JavaThread, so copy and clear pending exception. 720178825Sdfr 72155682Smarkm // load and clear pending exception 722178825Sdfr __ movl(rax, Address(thread, Thread::pending_exception_offset())); 723178825Sdfr __ movl(Address(thread, Thread::pending_exception_offset()), NULL_WORD); 724178825Sdfr 725178825Sdfr // check that there is really a valid exception 726178825Sdfr __ verify_not_null_oop(rax); 727178825Sdfr 728178825Sdfr // load throwing pc: this is the return address of the stub 729178825Sdfr __ movl(rdx, Address(rsp, return_off * BytesPerWord)); 730178825Sdfr 731178825Sdfr#ifdef ASSERT 732233294Sstas // check that fields in JavaThread for exception oop and issuing pc are empty 733178825Sdfr Label oop_empty; 734178825Sdfr __ cmpoop(Address(thread, JavaThread::exception_oop_offset()), 0); 735178825Sdfr __ jcc(Assembler::equal, oop_empty); 736178825Sdfr __ stop("exception oop must be empty"); 737178825Sdfr __ bind(oop_empty); 738178825Sdfr 739178825Sdfr Label pc_empty; 740178825Sdfr __ cmpl(Address(thread, JavaThread::exception_pc_offset()), 0); 741178825Sdfr __ jcc(Assembler::equal, pc_empty); 742233294Sstas __ stop("exception pc must be empty"); 743178825Sdfr __ bind(pc_empty); 744178825Sdfr#endif 74555682Smarkm 74655682Smarkm // store exception oop and throwing pc to JavaThread 74755682Smarkm __ movl(Address(thread, JavaThread::exception_oop_offset()), rax); 74855682Smarkm __ movl(Address(thread, JavaThread::exception_pc_offset()), rdx); 74955682Smarkm 75055682Smarkm restore_live_registers(sasm); 751178825Sdfr 75272445Sassar __ leave(); 75372445Sassar __ addl(rsp, 4); // remove return address from stack 75472445Sassar 75572445Sassar // Forward the exception directly to deopt blob. We can blow no 75672445Sassar // registers and must leave throwing pc on the stack. A patch may 75772445Sassar // have values live in registers so the entry point with the 75872445Sassar // exception in tls. 75972445Sassar __ jump(RuntimeAddress(deopt_blob->unpack_with_exception_in_tls())); 76072445Sassar 76172445Sassar __ bind(L); 76272445Sassar } 76372445Sassar 76472445Sassar 76572445Sassar // Runtime will return true if the nmethod has been deoptimized during 76672445Sassar // the patching process. In that case we must do a deopt reexecute instead. 76772445Sassar 76872445Sassar Label reexecuteEntry, cont; 76972445Sassar 77072445Sassar __ testl(rax, rax); // have we deoptimized? 77172445Sassar __ jcc(Assembler::equal, cont); // no 77272445Sassar 77372445Sassar // Will reexecute. Proper return address is already on the stack we just restore 77472445Sassar // registers, pop all of our frame but the return address and jump to the deopt blob 77572445Sassar restore_live_registers(sasm); 776178825Sdfr __ leave(); 77772445Sassar __ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); 77872445Sassar 77972445Sassar __ bind(cont); 78072445Sassar restore_live_registers(sasm); 78172445Sassar __ leave(); 78272445Sassar __ ret(0); 78372445Sassar 784178825Sdfr return oop_maps; 78572445Sassar 786178825Sdfr} 787178825Sdfr 78872445Sassar 78972445SassarOopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { 79072445Sassar 79172445Sassar // for better readability 79272445Sassar const bool must_gc_arguments = true; 79372445Sassar const bool dont_gc_arguments = false; 79455682Smarkm 79555682Smarkm // default value; overwritten for some optimized stubs that are called from methods that do not use the fpu 79655682Smarkm bool save_fpu_registers = true; 79755682Smarkm 79855682Smarkm // stub code & info for the different stubs 79955682Smarkm OopMapSet* oop_maps = NULL; 800178825Sdfr switch (id) { 80155682Smarkm case forward_exception_id: 80255682Smarkm { 803178825Sdfr // we're handling an exception in the context of a compiled 804178825Sdfr // frame. The registers have been saved in the standard 805178825Sdfr // places. Perform an exception lookup in the caller and 806178825Sdfr // dispatch to the handler if found. Otherwise unwind and 80755682Smarkm // dispatch to the callers exception handler. 80855682Smarkm 80955682Smarkm const Register thread = rdi; 81055682Smarkm const Register exception_oop = rax; 81155682Smarkm const Register exception_pc = rdx; 81255682Smarkm 81355682Smarkm // load pending exception oop into rax, 814178825Sdfr __ movl(exception_oop, Address(thread, Thread::pending_exception_offset())); 81555682Smarkm // clear pending exception 81655682Smarkm __ movl(Address(thread, Thread::pending_exception_offset()), NULL_WORD); 81755682Smarkm 81855682Smarkm // load issuing PC (the return address for this stub) into rdx 81955682Smarkm __ movl(exception_pc, Address(rbp, 1*BytesPerWord)); 82055682Smarkm 821178825Sdfr // make sure that the vm_results are cleared (may be unnecessary) 822178825Sdfr __ movl(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); 823178825Sdfr __ movl(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); 824178825Sdfr 825178825Sdfr // verify that that there is really a valid exception in rax, 826178825Sdfr __ verify_not_null_oop(exception_oop); 827178825Sdfr 82855682Smarkm 829178825Sdfr oop_maps = new OopMapSet(); 83055682Smarkm OopMap* oop_map = generate_oop_map(sasm, 1); 83155682Smarkm generate_handle_exception(sasm, oop_maps, oop_map); 83255682Smarkm __ stop("should not reach here"); 83355682Smarkm } 83455682Smarkm break; 83555682Smarkm 83655682Smarkm case new_instance_id: 83755682Smarkm case fast_new_instance_id: 83855682Smarkm case fast_new_instance_init_check_id: 83955682Smarkm { 84055682Smarkm Register klass = rdx; // Incoming 84155682Smarkm Register obj = rax; // Result 84255682Smarkm 843102644Snectar if (id == new_instance_id) { 84455682Smarkm __ set_info("new_instance", dont_gc_arguments); 84555682Smarkm } else if (id == fast_new_instance_id) { 84655682Smarkm __ set_info("fast new_instance", dont_gc_arguments); 84755682Smarkm } else { 84855682Smarkm assert(id == fast_new_instance_init_check_id, "bad StubID"); 849233294Sstas __ set_info("fast new_instance init check", dont_gc_arguments); 850233294Sstas } 851233294Sstas 852178825Sdfr if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) && 85355682Smarkm UseTLAB && FastTLABRefill) { 85455682Smarkm Label slow_path; 85555682Smarkm Register obj_size = rcx; 856178825Sdfr Register t1 = rbx; 857178825Sdfr Register t2 = rsi; 858178825Sdfr assert_different_registers(klass, obj, obj_size, t1, t2); 85955682Smarkm 86055682Smarkm __ pushl(rdi); 861178825Sdfr __ pushl(rbx); 86255682Smarkm 863178825Sdfr if (id == fast_new_instance_init_check_id) { 864178825Sdfr // make sure the klass is initialized 86555682Smarkm __ cmpl(Address(klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), instanceKlass::fully_initialized); 86655682Smarkm __ jcc(Assembler::notEqual, slow_path); 867178825Sdfr } 868178825Sdfr 869102644Snectar#ifdef ASSERT 870178825Sdfr // assert object can be fast path allocated 871178825Sdfr { 872178825Sdfr Label ok, not_ok; 87355682Smarkm __ movl(obj_size, Address(klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc))); 874178825Sdfr __ cmpl(obj_size, 0); // make sure it's an instance (LH > 0) 875233294Sstas __ jcc(Assembler::lessEqual, not_ok); 876233294Sstas __ testl(obj_size, Klass::_lh_instance_slow_path_bit); 87755682Smarkm __ jcc(Assembler::zero, ok); 87855682Smarkm __ bind(not_ok); 879102644Snectar __ stop("assert(can be fast path allocated)"); 880178825Sdfr __ should_not_reach_here(); 881178825Sdfr __ bind(ok); 882178825Sdfr } 883233294Sstas#endif // ASSERT 884178825Sdfr 885233294Sstas // if we got here then the TLAB allocation failed, so try 886233294Sstas // refilling the TLAB or allocating directly from eden. 887233294Sstas Label retry_tlab, try_eden; 888233294Sstas __ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass) 889233294Sstas 890233294Sstas __ bind(retry_tlab); 891178825Sdfr 892178825Sdfr // get the instance size 893178825Sdfr __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); 894178825Sdfr __ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path); 895178825Sdfr __ initialize_object(obj, klass, obj_size, 0, t1, t2); 89655682Smarkm __ verify_oop(obj); 897178825Sdfr __ popl(rbx); 898233294Sstas __ popl(rdi); 899233294Sstas __ ret(0); 90055682Smarkm 901178825Sdfr __ bind(try_eden); 902178825Sdfr // get the instance size 903178825Sdfr __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); 904233294Sstas __ eden_allocate(obj, obj_size, 0, t1, slow_path); 905178825Sdfr __ initialize_object(obj, klass, obj_size, 0, t1, t2); 906233294Sstas __ verify_oop(obj); 907233294Sstas __ popl(rbx); 908233294Sstas __ popl(rdi); 909178825Sdfr __ ret(0); 910178825Sdfr 91155682Smarkm __ bind(slow_path); 912178825Sdfr __ popl(rbx); 913178825Sdfr __ popl(rdi); 914178825Sdfr } 915233294Sstas 916233294Sstas __ enter(); 917178825Sdfr OopMap* map = save_live_registers(sasm, 2); 91855682Smarkm int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass); 91955682Smarkm oop_maps = new OopMapSet(); 92055682Smarkm oop_maps->add_gc_map(call_offset, map); 92155682Smarkm restore_live_registers_except_rax(sasm); 92255682Smarkm __ verify_oop(obj); 92355682Smarkm __ leave(); 92455682Smarkm __ ret(0); 92555682Smarkm 92655682Smarkm // rax,: new instance 927178825Sdfr } 928178825Sdfr 92955682Smarkm break; 93055682Smarkm 93155682Smarkm#ifdef TIERED 93255682Smarkm case counter_overflow_id: 93355682Smarkm { 93455682Smarkm Register bci = rax; 93555682Smarkm __ enter(); 93655682Smarkm OopMap* map = save_live_registers(sasm, 2); 93755682Smarkm // Retrieve bci 93855682Smarkm __ movl(bci, Address(rbp, 2*BytesPerWord)); 93955682Smarkm int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci); 94072445Sassar oop_maps = new OopMapSet(); 94172445Sassar oop_maps->add_gc_map(call_offset, map); 94255682Smarkm restore_live_registers(sasm); 943233294Sstas __ leave(); 944233294Sstas __ ret(0); 94555682Smarkm } 94655682Smarkm break; 94755682Smarkm#endif // TIERED 94872445Sassar 94972445Sassar case new_type_array_id: 95072445Sassar case new_object_array_id: 95172445Sassar { 95272445Sassar Register length = rbx; // Incoming 95372445Sassar Register klass = rdx; // Incoming 95472445Sassar Register obj = rax; // Result 95572445Sassar 95672445Sassar if (id == new_type_array_id) { 957178825Sdfr __ set_info("new_type_array", dont_gc_arguments); 95872445Sassar } else { 95972445Sassar __ set_info("new_object_array", dont_gc_arguments); 96072445Sassar } 96172445Sassar 96272445Sassar#ifdef ASSERT 96372445Sassar // assert object type is really an array of the proper kind 96472445Sassar { 96572445Sassar Label ok; 96672445Sassar Register t0 = obj; 96772445Sassar __ movl(t0, Address(klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc))); 96872445Sassar __ sarl(t0, Klass::_lh_array_tag_shift); 96972445Sassar int tag = ((id == new_type_array_id) 97072445Sassar ? Klass::_lh_array_tag_type_value 971178825Sdfr : Klass::_lh_array_tag_obj_value); 97272445Sassar __ cmpl(t0, tag); 97372445Sassar __ jcc(Assembler::equal, ok); 97472445Sassar __ stop("assert(is an array klass)"); 97572445Sassar __ should_not_reach_here(); 97672445Sassar __ bind(ok); 97772445Sassar } 97872445Sassar#endif // ASSERT 97972445Sassar 98072445Sassar if (UseTLAB && FastTLABRefill) { 98172445Sassar Register arr_size = rsi; 98272445Sassar Register t1 = rcx; // must be rcx for use as shift count 98372445Sassar Register t2 = rdi; 98472445Sassar Label slow_path; 985178825Sdfr assert_different_registers(length, klass, obj, arr_size, t1, t2); 986233294Sstas 987233294Sstas // check that array length is small enough for fast path. 988178825Sdfr __ cmpl(length, C1_MacroAssembler::max_array_allocation_length); 989178825Sdfr __ jcc(Assembler::above, slow_path); 990178825Sdfr 991178825Sdfr // if we got here then the TLAB allocation failed, so try 992178825Sdfr // refilling the TLAB or allocating directly from eden. 993178825Sdfr Label retry_tlab, try_eden; 994178825Sdfr __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx, & rdx 995178825Sdfr 996178825Sdfr __ bind(retry_tlab); 997178825Sdfr 998178825Sdfr // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) 999178825Sdfr __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); 1000178825Sdfr __ movl(arr_size, length); 1001178825Sdfr assert(t1 == rcx, "fixed register usage"); 1002178825Sdfr __ shll(arr_size /* by t1=rcx, mod 32 */); 1003178825Sdfr __ shrl(t1, Klass::_lh_header_size_shift); 1004178825Sdfr __ andl(t1, Klass::_lh_header_size_mask); 1005178825Sdfr __ addl(arr_size, t1); 1006233294Sstas __ addl(arr_size, MinObjAlignmentInBytesMask); // align up 1007233294Sstas __ andl(arr_size, ~MinObjAlignmentInBytesMask); 1008233294Sstas 1009233294Sstas __ tlab_allocate(obj, arr_size, 0, t1, t2, slow_path); // preserves arr_size 1010233294Sstas 1011233294Sstas __ initialize_header(obj, klass, length, t1, t2); 1012233294Sstas __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte))); 1013233294Sstas assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); 1014233294Sstas assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise"); 1015233294Sstas __ andl(t1, Klass::_lh_header_size_mask); 1016233294Sstas __ subl(arr_size, t1); // body length 1017233294Sstas __ addl(t1, obj); // body start 1018233294Sstas __ initialize_body(t1, arr_size, 0, t2); 1019233294Sstas __ verify_oop(obj); 1020233294Sstas __ ret(0); 1021233294Sstas 1022233294Sstas __ bind(try_eden); 1023233294Sstas // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) 1024233294Sstas __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); 1025233294Sstas __ movl(arr_size, length); 1026233294Sstas assert(t1 == rcx, "fixed register usage"); 1027233294Sstas __ shll(arr_size /* by t1=rcx, mod 32 */); 1028233294Sstas __ shrl(t1, Klass::_lh_header_size_shift); 1029233294Sstas __ andl(t1, Klass::_lh_header_size_mask); 1030233294Sstas __ addl(arr_size, t1); 1031233294Sstas __ addl(arr_size, MinObjAlignmentInBytesMask); // align up 1032233294Sstas __ andl(arr_size, ~MinObjAlignmentInBytesMask); 1033233294Sstas 1034233294Sstas __ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size 1035233294Sstas 1036233294Sstas __ initialize_header(obj, klass, length, t1, t2); 1037233294Sstas __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte))); 1038233294Sstas assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); 1039233294Sstas assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise"); 1040233294Sstas __ andl(t1, Klass::_lh_header_size_mask); 1041233294Sstas __ subl(arr_size, t1); // body length 1042233294Sstas __ addl(t1, obj); // body start 1043233294Sstas __ initialize_body(t1, arr_size, 0, t2); 1044233294Sstas __ verify_oop(obj); 1045233294Sstas __ ret(0); 1046233294Sstas 1047233294Sstas __ bind(slow_path); 1048233294Sstas } 1049233294Sstas 1050233294Sstas __ enter(); 1051233294Sstas OopMap* map = save_live_registers(sasm, 3); 1052233294Sstas int call_offset; 1053233294Sstas if (id == new_type_array_id) { 1054233294Sstas call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); 1055233294Sstas } else { 1056233294Sstas call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); 1057233294Sstas } 1058 1059 oop_maps = new OopMapSet(); 1060 oop_maps->add_gc_map(call_offset, map); 1061 restore_live_registers_except_rax(sasm); 1062 1063 __ verify_oop(obj); 1064 __ leave(); 1065 __ ret(0); 1066 1067 // rax,: new array 1068 } 1069 break; 1070 1071 case new_multi_array_id: 1072 { StubFrame f(sasm, "new_multi_array", dont_gc_arguments); 1073 // rax,: klass 1074 // rbx,: rank 1075 // rcx: address of 1st dimension 1076 OopMap* map = save_live_registers(sasm, 4); 1077 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx); 1078 1079 oop_maps = new OopMapSet(); 1080 oop_maps->add_gc_map(call_offset, map); 1081 restore_live_registers_except_rax(sasm); 1082 1083 // rax,: new multi array 1084 __ verify_oop(rax); 1085 } 1086 break; 1087 1088 case register_finalizer_id: 1089 { 1090 __ set_info("register_finalizer", dont_gc_arguments); 1091 1092 // The object is passed on the stack and we haven't pushed a 1093 // frame yet so it's one work away from top of stack. 1094 __ movl(rax, Address(rsp, 1 * BytesPerWord)); 1095 __ verify_oop(rax); 1096 1097 // load the klass and check the has finalizer flag 1098 Label register_finalizer; 1099 Register t = rsi; 1100 __ movl(t, Address(rax, oopDesc::klass_offset_in_bytes())); 1101 __ movl(t, Address(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc))); 1102 __ testl(t, JVM_ACC_HAS_FINALIZER); 1103 __ jcc(Assembler::notZero, register_finalizer); 1104 __ ret(0); 1105 1106 __ bind(register_finalizer); 1107 __ enter(); 1108 OopMap* oop_map = save_live_registers(sasm, 2 /*num_rt_args */); 1109 int call_offset = __ call_RT(noreg, noreg, 1110 CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), rax); 1111 oop_maps = new OopMapSet(); 1112 oop_maps->add_gc_map(call_offset, oop_map); 1113 1114 // Now restore all the live registers 1115 restore_live_registers(sasm); 1116 1117 __ leave(); 1118 __ ret(0); 1119 } 1120 break; 1121 1122 case throw_range_check_failed_id: 1123 { StubFrame f(sasm, "range_check_failed", dont_gc_arguments); 1124 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); 1125 } 1126 break; 1127 1128 case throw_index_exception_id: 1129 { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); 1130 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); 1131 } 1132 break; 1133 1134 case throw_div0_exception_id: 1135 { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments); 1136 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); 1137 } 1138 break; 1139 1140 case throw_null_pointer_exception_id: 1141 { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments); 1142 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); 1143 } 1144 break; 1145 1146 case handle_exception_nofpu_id: 1147 save_fpu_registers = false; 1148 // fall through 1149 case handle_exception_id: 1150 { StubFrame f(sasm, "handle_exception", dont_gc_arguments); 1151 oop_maps = new OopMapSet(); 1152 OopMap* oop_map = save_live_registers(sasm, 1, save_fpu_registers); 1153 generate_handle_exception(sasm, oop_maps, oop_map, save_fpu_registers); 1154 } 1155 break; 1156 1157 case unwind_exception_id: 1158 { __ set_info("unwind_exception", dont_gc_arguments); 1159 // note: no stubframe since we are about to leave the current 1160 // activation and we are calling a leaf VM function only. 1161 generate_unwind_exception(sasm); 1162 } 1163 break; 1164 1165 case throw_array_store_exception_id: 1166 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); 1167 // tos + 0: link 1168 // + 1: return address 1169 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), false); 1170 } 1171 break; 1172 1173 case throw_class_cast_exception_id: 1174 { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments); 1175 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); 1176 } 1177 break; 1178 1179 case throw_incompatible_class_change_error_id: 1180 { StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments); 1181 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); 1182 } 1183 break; 1184 1185 case slow_subtype_check_id: 1186 { 1187 enum layout { 1188 rax_off, 1189 rcx_off, 1190 rsi_off, 1191 rdi_off, 1192 saved_rbp_off, 1193 return_off, 1194 sub_off, 1195 super_off, 1196 framesize 1197 }; 1198 1199 __ set_info("slow_subtype_check", dont_gc_arguments); 1200 __ pushl(rdi); 1201 __ pushl(rsi); 1202 __ pushl(rcx); 1203 __ pushl(rax); 1204 __ movl(rsi, Address(rsp, (super_off - 1) * BytesPerWord)); // super 1205 __ movl(rax, Address(rsp, (sub_off - 1) * BytesPerWord)); // sub 1206 1207 __ movl(rdi,Address(rsi,sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())); 1208 __ movl(rcx,Address(rdi,arrayOopDesc::length_offset_in_bytes())); 1209 __ addl(rdi,arrayOopDesc::base_offset_in_bytes(T_OBJECT)); 1210 1211 Label miss; 1212 __ repne_scan(); 1213 __ jcc(Assembler::notEqual, miss); 1214 __ movl(Address(rsi,sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax); 1215 __ movl(Address(rsp, (super_off - 1) * BytesPerWord), 1); // result 1216 __ popl(rax); 1217 __ popl(rcx); 1218 __ popl(rsi); 1219 __ popl(rdi); 1220 __ ret(0); 1221 1222 __ bind(miss); 1223 __ movl(Address(rsp, (super_off - 1) * BytesPerWord), 0); // result 1224 __ popl(rax); 1225 __ popl(rcx); 1226 __ popl(rsi); 1227 __ popl(rdi); 1228 __ ret(0); 1229 } 1230 break; 1231 1232 case monitorenter_nofpu_id: 1233 save_fpu_registers = false; 1234 // fall through 1235 case monitorenter_id: 1236 { 1237 StubFrame f(sasm, "monitorenter", dont_gc_arguments); 1238 OopMap* map = save_live_registers(sasm, 3, save_fpu_registers); 1239 1240 f.load_argument(1, rax); // rax,: object 1241 f.load_argument(0, rbx); // rbx,: lock address 1242 1243 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), rax, rbx); 1244 1245 oop_maps = new OopMapSet(); 1246 oop_maps->add_gc_map(call_offset, map); 1247 restore_live_registers(sasm, save_fpu_registers); 1248 } 1249 break; 1250 1251 case monitorexit_nofpu_id: 1252 save_fpu_registers = false; 1253 // fall through 1254 case monitorexit_id: 1255 { 1256 StubFrame f(sasm, "monitorexit", dont_gc_arguments); 1257 OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); 1258 1259 f.load_argument(0, rax); // rax,: lock address 1260 1261 // note: really a leaf routine but must setup last java sp 1262 // => use call_RT for now (speed can be improved by 1263 // doing last java sp setup manually) 1264 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), rax); 1265 1266 oop_maps = new OopMapSet(); 1267 oop_maps->add_gc_map(call_offset, map); 1268 restore_live_registers(sasm, save_fpu_registers); 1269 1270 } 1271 break; 1272 1273 case access_field_patching_id: 1274 { StubFrame f(sasm, "access_field_patching", dont_gc_arguments); 1275 // we should set up register map 1276 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); 1277 } 1278 break; 1279 1280 case load_klass_patching_id: 1281 { StubFrame f(sasm, "load_klass_patching", dont_gc_arguments); 1282 // we should set up register map 1283 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); 1284 } 1285 break; 1286 1287 case jvmti_exception_throw_id: 1288 { // rax,: exception oop 1289 StubFrame f(sasm, "jvmti_exception_throw", dont_gc_arguments); 1290 // Preserve all registers across this potentially blocking call 1291 const int num_rt_args = 2; // thread, exception oop 1292 OopMap* map = save_live_registers(sasm, num_rt_args); 1293 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), rax); 1294 oop_maps = new OopMapSet(); 1295 oop_maps->add_gc_map(call_offset, map); 1296 restore_live_registers(sasm); 1297 } 1298 break; 1299 1300 case dtrace_object_alloc_id: 1301 { // rax,: object 1302 StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); 1303 // we can't gc here so skip the oopmap but make sure that all 1304 // the live registers get saved. 1305 save_live_registers(sasm, 1); 1306 1307 __ pushl(rax); 1308 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc))); 1309 __ popl(rax); 1310 1311 restore_live_registers(sasm); 1312 } 1313 break; 1314 1315 case fpu2long_stub_id: 1316 { 1317 // rax, and rdx are destroyed, but should be free since the result is returned there 1318 // preserve rsi,ecx 1319 __ pushl(rsi); 1320 __ pushl(rcx); 1321 1322 // check for NaN 1323 Label return0, do_return, return_min_jlong, do_convert; 1324 1325 Address value_high_word(rsp, 8); 1326 Address value_low_word(rsp, 4); 1327 Address result_high_word(rsp, 16); 1328 Address result_low_word(rsp, 12); 1329 1330 __ subl(rsp, 20); 1331 __ fst_d(value_low_word); 1332 __ movl(rax, value_high_word); 1333 __ andl(rax, 0x7ff00000); 1334 __ cmpl(rax, 0x7ff00000); 1335 __ jcc(Assembler::notEqual, do_convert); 1336 __ movl(rax, value_high_word); 1337 __ andl(rax, 0xfffff); 1338 __ orl(rax, value_low_word); 1339 __ jcc(Assembler::notZero, return0); 1340 1341 __ bind(do_convert); 1342 __ fnstcw(Address(rsp, 0)); 1343 __ movzxw(rax, Address(rsp, 0)); 1344 __ orl(rax, 0xc00); 1345 __ movw(Address(rsp, 2), rax); 1346 __ fldcw(Address(rsp, 2)); 1347 __ fwait(); 1348 __ fistp_d(result_low_word); 1349 __ fldcw(Address(rsp, 0)); 1350 __ fwait(); 1351 __ movl(rax, result_low_word); 1352 __ movl(rdx, result_high_word); 1353 __ movl(rcx, rax); 1354 // What the heck is the point of the next instruction??? 1355 __ xorl(rcx, 0x0); 1356 __ movl(rsi, 0x80000000); 1357 __ xorl(rsi, rdx); 1358 __ orl(rcx, rsi); 1359 __ jcc(Assembler::notEqual, do_return); 1360 __ fldz(); 1361 __ fcomp_d(value_low_word); 1362 __ fnstsw_ax(); 1363 __ sahf(); 1364 __ jcc(Assembler::above, return_min_jlong); 1365 // return max_jlong 1366 __ movl(rdx, 0x7fffffff); 1367 __ movl(rax, 0xffffffff); 1368 __ jmp(do_return); 1369 1370 __ bind(return_min_jlong); 1371 __ movl(rdx, 0x80000000); 1372 __ xorl(rax, rax); 1373 __ jmp(do_return); 1374 1375 __ bind(return0); 1376 __ fpop(); 1377 __ xorl(rdx,rdx); 1378 __ xorl(rax,rax); 1379 1380 __ bind(do_return); 1381 __ addl(rsp, 20); 1382 __ popl(rcx); 1383 __ popl(rsi); 1384 __ ret(0); 1385 } 1386 break; 1387 1388 default: 1389 { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); 1390 __ movl(rax, (int)id); 1391 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax); 1392 __ should_not_reach_here(); 1393 } 1394 break; 1395 } 1396 return oop_maps; 1397} 1398 1399#undef __ 1400