1 #ifdef USE_PRAGMA_IDENT_SRC 2 #pragma ident "@(#)runtime_x86_32.cpp 1.113 07/09/17 09:26:02 JVM" 3 #endif 4 /* 5 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 23 * CA 95054 USA or visit www.sun.com if you need additional information or 24 * have any questions. 25 * 26 */ 27 28 29 #include "incls/_precompiled.incl" 30 #include "incls/_runtime_x86_32.cpp.incl" 31 32 #define __ masm-> 33 34 ExceptionBlob* OptoRuntime::_exception_blob; 35 36 //------------------------------generate_exception_blob--------------------------- 37 // creates exception blob at the end 38 // Using exception blob, this code is jumped from a compiled method. 39 // 40 // Given an exception pc at a call we call into the runtime for the 41 // handler in this method. This handler might merely restore state 42 // (i.e. callee save registers) unwind the frame and jump to the 43 // exception handler for the nmethod if there is no Java level handler 44 // for the nmethod. 45 // 46 // This code is entered with a jmp. 47 // 48 // Arguments: 49 // rax,: exception oop 50 // rdx: exception pc 51 // 52 // Results: 53 // rax,: exception oop 54 // rdx: exception pc in caller or ??? 55 // destination: exception handler of caller 56 // 57 // Note: the exception pc MUST be at a call (precise debug information) 58 // Only register rax, rdx, rcx are not callee saved. 59 // 60 61 void OptoRuntime::generate_exception_blob() { 62 63 // Capture info about frame layout 64 enum layout { 65 thread_off, // last_java_sp 66 // The frame sender code expects that rbp will be in the "natural" place and 67 // will override any oopMap setting for it. We must therefore force the layout 68 // so that it agrees with the frame sender code. 69 rbp_off, 70 return_off, // slot for return address 71 framesize 72 }; 73 74 // allocate space for the code 75 ResourceMark rm; 76 // setup code generation tools 77 CodeBuffer buffer("exception_blob", 512, 512); 78 MacroAssembler* masm = new MacroAssembler(&buffer); 79 80 OopMapSet *oop_maps = new OopMapSet(); 81 82 address start = __ pc(); 83 84 __ pushl(rdx); 85 __ subl(rsp, return_off * wordSize); // Prolog! 86 87 // rbp, location is implicitly known 88 __ movl(Address(rsp,rbp_off *wordSize),rbp); 89 90 // Store exception in Thread object. We cannot pass any arguments to the 91 // handle_exception call, since we do not want to make any assumption 92 // about the size of the frame where the exception happened in. 93 __ get_thread(rcx); 94 __ movl(Address(rcx, JavaThread::exception_oop_offset()), rax); 95 __ movl(Address(rcx, JavaThread::exception_pc_offset()), rdx); 96 97 // This call does all the hard work. It checks if an exception handler 98 // exists in the method. 99 // If so, it returns the handler address. 100 // If not, it prepares for stack-unwinding, restoring the callee-save 101 // registers of the frame being removed. 102 // 103 __ movl(Address(rsp, thread_off * wordSize), rcx); // Thread is first argument 104 __ set_last_Java_frame(rcx, noreg, noreg, NULL); 105 106 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); 107 108 // No registers to map, rbp is known implicitly 109 oop_maps->add_gc_map( __ pc() - start, new OopMap( framesize, 0 )); 110 __ get_thread(rcx); 111 __ reset_last_Java_frame(rcx, false, false); 112 113 // Restore callee-saved registers 114 __ movl(rbp, Address(rsp, rbp_off * wordSize)); 115 116 __ addl(rsp, return_off * wordSize); // Epilog! 117 __ popl(rdx); // Exception pc 118 119 120 // rax,: exception handler for given <exception oop/exception pc> 121 122 // We have a handler in rax, (could be deopt blob) 123 // rdx - throwing pc, deopt blob will need it. 124 125 __ pushl(rax); 126 127 // rcx contains handler address 128 129 __ get_thread(rcx); // TLS 130 // Get the exception 131 __ movl(rax, Address(rcx, JavaThread::exception_oop_offset())); 132 // Get the exception pc in case we are deoptimized 133 __ movl(rdx, Address(rcx, JavaThread::exception_pc_offset())); 134 #ifdef ASSERT 135 __ movl(Address(rcx, JavaThread::exception_handler_pc_offset()), 0); 136 __ movl(Address(rcx, JavaThread::exception_pc_offset()), 0); 137 #endif 138 // Clear the exception oop so GC no longer processes it as a root. 139 __ movl(Address(rcx, JavaThread::exception_oop_offset()), 0); 140 141 __ popl(rcx); 142 143 // rax,: exception oop 144 // rcx: exception handler 145 // rdx: exception pc 146 __ jmp (rcx); 147 148 // ------------- 149 // make sure all code is generated 150 masm->flush(); 151 152 _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize); 153 }