duke@435: /* xdono@1014: * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: duke@435: #include "incls/_precompiled.incl" duke@435: #include "incls/_runtime_x86_32.cpp.incl" duke@435: duke@435: #define __ masm-> duke@435: duke@435: ExceptionBlob* OptoRuntime::_exception_blob; duke@435: duke@435: //------------------------------generate_exception_blob--------------------------- duke@435: // creates exception blob at the end duke@435: // Using exception blob, this code is jumped from a compiled method. duke@435: // duke@435: // Given an exception pc at a call we call into the runtime for the duke@435: // handler in this method. This handler might merely restore state duke@435: // (i.e. callee save registers) unwind the frame and jump to the duke@435: // exception handler for the nmethod if there is no Java level handler duke@435: // for the nmethod. duke@435: // duke@435: // This code is entered with a jmp. duke@435: // duke@435: // Arguments: twisti@1570: // rax: exception oop duke@435: // rdx: exception pc duke@435: // duke@435: // Results: twisti@1570: // rax: exception oop duke@435: // rdx: exception pc in caller or ??? duke@435: // destination: exception handler of caller duke@435: // duke@435: // Note: the exception pc MUST be at a call (precise debug information) duke@435: // Only register rax, rdx, rcx are not callee saved. duke@435: // duke@435: duke@435: void OptoRuntime::generate_exception_blob() { duke@435: duke@435: // Capture info about frame layout duke@435: enum layout { duke@435: thread_off, // last_java_sp duke@435: // The frame sender code expects that rbp will be in the "natural" place and duke@435: // will override any oopMap setting for it. We must therefore force the layout duke@435: // so that it agrees with the frame sender code. duke@435: rbp_off, duke@435: return_off, // slot for return address duke@435: framesize duke@435: }; duke@435: duke@435: // allocate space for the code duke@435: ResourceMark rm; duke@435: // setup code generation tools duke@435: CodeBuffer buffer("exception_blob", 512, 512); duke@435: MacroAssembler* masm = new MacroAssembler(&buffer); duke@435: duke@435: OopMapSet *oop_maps = new OopMapSet(); duke@435: duke@435: address start = __ pc(); duke@435: never@739: __ push(rdx); never@739: __ subptr(rsp, return_off * wordSize); // Prolog! duke@435: duke@435: // rbp, location is implicitly known never@739: __ movptr(Address(rsp,rbp_off *wordSize), rbp); duke@435: duke@435: // Store exception in Thread object. We cannot pass any arguments to the duke@435: // handle_exception call, since we do not want to make any assumption duke@435: // about the size of the frame where the exception happened in. duke@435: __ get_thread(rcx); never@739: __ movptr(Address(rcx, JavaThread::exception_oop_offset()), rax); never@739: __ movptr(Address(rcx, JavaThread::exception_pc_offset()), rdx); duke@435: duke@435: // This call does all the hard work. It checks if an exception handler duke@435: // exists in the method. duke@435: // If so, it returns the handler address. duke@435: // If not, it prepares for stack-unwinding, restoring the callee-save duke@435: // registers of the frame being removed. duke@435: // never@739: __ movptr(Address(rsp, thread_off * wordSize), rcx); // Thread is first argument duke@435: __ set_last_Java_frame(rcx, noreg, noreg, NULL); duke@435: duke@435: __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); duke@435: duke@435: // No registers to map, rbp is known implicitly duke@435: oop_maps->add_gc_map( __ pc() - start, new OopMap( framesize, 0 )); duke@435: __ get_thread(rcx); duke@435: __ reset_last_Java_frame(rcx, false, false); duke@435: duke@435: // Restore callee-saved registers never@739: __ movptr(rbp, Address(rsp, rbp_off * wordSize)); duke@435: never@739: __ addptr(rsp, return_off * wordSize); // Epilog! never@739: __ pop(rdx); // Exception pc duke@435: twisti@1570: // rax: exception handler for given duke@435: twisti@1570: // Restore SP from BP if the exception PC is a MethodHandle call. twisti@1570: __ cmpl(Address(rcx, JavaThread::is_method_handle_exception_offset()), 0); twisti@1570: __ cmovptr(Assembler::notEqual, rsp, rbp); duke@435: duke@435: // We have a handler in rax, (could be deopt blob) duke@435: // rdx - throwing pc, deopt blob will need it. duke@435: never@739: __ push(rax); duke@435: duke@435: // Get the exception never@739: __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); duke@435: // Get the exception pc in case we are deoptimized never@739: __ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset())); duke@435: #ifdef ASSERT xlu@947: __ movptr(Address(rcx, JavaThread::exception_handler_pc_offset()), NULL_WORD); xlu@947: __ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD); duke@435: #endif duke@435: // Clear the exception oop so GC no longer processes it as a root. xlu@947: __ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD); duke@435: never@739: __ pop(rcx); duke@435: twisti@1570: // rax: exception oop duke@435: // rcx: exception handler duke@435: // rdx: exception pc duke@435: __ jmp (rcx); duke@435: duke@435: // ------------- duke@435: // make sure all code is generated duke@435: masm->flush(); duke@435: duke@435: _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize); duke@435: }