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